-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor JceMasterKey to extract logic to be shared by raw keyrings. #139
Conversation
*Issue #, if available:* #102 *Description of changes:* In anticipation of the RawAesKeyring and RawRsaKeyring needing logic currently embedded in the JceMasterKey, this change extracts that logic into the JceKeyCipher class so it may be shared. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. - [ ] Were any files moved? Moving files changes their URL, which breaks all hyperlinks to the files.
if (tagLen != TAG_LENGTH) { | ||
throw new InvalidKeyException(String.format("Authentication tag length must be %s", TAG_LENGTH)); | ||
} | ||
|
||
if (nonceLen != NONCE_LENGTH) { | ||
throw new InvalidKeyException(String.format("Initialization vector (IV) length must be %s", NONCE_LENGTH)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only part of this PR that isn't a refactor. I made this change to bring this in line with the RawAesKeyring spec
final byte[] provInfo = new byte[keyNameBytes.length + wData.extraInfo.length]; | ||
System.arraycopy(keyNameBytes, 0, provInfo, 0, keyNameBytes.length); | ||
System.arraycopy(wData.extraInfo, 0, provInfo, keyNameBytes.length, wData.extraInfo.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If wData.extraInfo.length==0
, then we should short-circuit this to avoid extra data-copies and allocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
private static byte[] specToBytes(final GCMParameterSpec spec) { | ||
final byte[] nonce = spec.getIV(); | ||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NitPick: Since we know exactly how long this will be, it's probably more efficient to use a ByteBuffer
than a ByteArrayOutputStream
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to ByteBuffer, it simplifies the code as well
dis.readFully(nonce); | ||
return new GCMParameterSpec(tagLen, nonce); | ||
} catch (final IOException ex) { | ||
throw new AssertionError("Impossible exception", ex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really impossible? I suspect that if the data is too short you'll get an IOException
. I'd just rethrow it as an InvalidKeyException
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I'm using a ByteBuffer it is impossible (ByteBuffer doesn't throw IOExceptions). I'm explicitly checking the data size against the nonce length now.
} | ||
|
||
private static GCMParameterSpec bytesToSpec(final byte[] data, final int offset) throws InvalidKeyException { | ||
final ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, data.length - offset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NitPick: Same comment about ByteBuffer
probably being more efficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
private static final int NONCE_LENGTH = 12; | ||
private static final int TAG_LENGTH = 128; | ||
private static final String TRANSFORMATION = "AES/GCM/NoPadding"; | ||
private final SecureRandom rnd = new SecureRandom(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this and use Utils.getSecureRandom()
exactly when you need it. (This avoids both creating more instances than you need and thread-contention.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I didn't see Utils.getSecureRandom until recently and forgot to go back and update this change
WrappingData buildWrappingCipher(final Key key, final Map<String, String> encryptionContext) | ||
throws GeneralSecurityException { | ||
final byte[] nonce = new byte[NONCE_LENGTH]; | ||
rnd.nextBytes(nonce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Utils.getSecureRandom().nextBytes(nonce);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// We require BouncyCastle to avoid some bugs in the default Java implementation | ||
// of OAEP. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an old comment and should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted
private static final Logger LOGGER = Logger.getLogger(JceMasterKey.class.getName()); | ||
private static final byte[] EMPTY_ARRAY = new byte[0]; | ||
|
||
public class JceMasterKey extends MasterKey<JceMasterKey> { | ||
private final SecureRandom rnd = new SecureRandom(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made suggested changes
throw new InvalidKeyException(String.format("Authentication tag length must be %s", TAG_LENGTH)); | ||
} | ||
final int tagLen = buffer.getInt(); | ||
final int nonceLen = buffer.getInt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the length is too short, youBufferUnderflowException
which should be caught and rethrown as an InvalidKeyException.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defined a SPEC_LENGTH constant that I validate against
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
* Add a basic example for encrypting and decrypting with a KMS CMK (#136) * *Issue #, if available:* #108 *Description of changes:* Add a basic example for encrypting and decrypting with a KMS CMK. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. # Check any applicable: - [ ] Were any files moved? Moving files changes their URL, which breaks all hyperlinks to the files. * Add test and Maven plugin to include examples directory as test source * Update docs in prep for 1.6.1 (#133) * Update docs in prep for 1.6.1 * Actually bump version for release * Fix for new versions of gpg * Refactor JceMasterKey to extract logic to be shared by raw keyrings. (#139) * Refactor JceMasterKey to extract logic to be shared by raw keyrings. *Issue #, if available:* #102 *Description of changes:* In anticipation of the RawAesKeyring and RawRsaKeyring needing logic currently embedded in the JceMasterKey, this change extracts that logic into the JceKeyCipher class so it may be shared. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. - [ ] Were any files moved? Moving files changes their URL, which breaks all hyperlinks to the files. * fix: The final frame can not be larger than the Frame Length (#166) * Add validation to ensure the length of the final frame in the final frame header does not exceed the frame size specified in the message header. * Validate that frame length is positive for framed data * Reverting removal of variable frame length code * Reverting removal of variable frame length code * Fix spacing after if Co-authored-by: SalusaSecondus <[email protected]> Co-authored-by: Greg Rubin <[email protected]>
Issue #, if available: #102
Description of changes:
In anticipation of the RawAesKeyring and RawRsaKeyring needing logic currently embedded in the JceMasterKey, this change extracts that logic into the JceKeyCipher class so it may be shared.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.