Skip to content
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

Merged
merged 9 commits into from
Nov 8, 2019

Conversation

WesleyRosenblum
Copy link
Contributor

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.

*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.
Comment on lines 64 to 70
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));
}
Copy link
Contributor Author

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

Comment on lines 93 to 95
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);
Copy link
Contributor

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.

Copy link
Contributor Author

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();
Copy link
Contributor

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

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();
Copy link
Contributor

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.)

Copy link
Contributor Author

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);
Copy link
Contributor

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);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 104 to 105
// We require BouncyCastle to avoid some bugs in the default Java implementation
// of OAEP.
Copy link
Contributor

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.

Copy link
Contributor Author

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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Copy link
Contributor Author

@WesleyRosenblum WesleyRosenblum left a 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();
Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor

@SalusaSecondus SalusaSecondus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@WesleyRosenblum WesleyRosenblum merged commit 4fdc309 into master Nov 8, 2019
@WesleyRosenblum WesleyRosenblum deleted the jcekeycipher branch February 12, 2020 02:25
WesleyRosenblum added a commit that referenced this pull request Apr 7, 2020
* 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants