use of javax.crypto.spec.GCMParameterSpec in project tink by google.
the class AndroidKeystoreAesGcm method decrypt.
@Override
public byte[] decrypt(final byte[] ciphertext, final byte[] aad) throws GeneralSecurityException {
if (ciphertext.length < IV_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES) {
throw new GeneralSecurityException("ciphertext too short");
}
GCMParameterSpec params = new GCMParameterSpec(8 * TAG_SIZE_IN_BYTES, ciphertext, 0, IV_SIZE_IN_BYTES);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.updateAAD(aad);
return cipher.doFinal(ciphertext, IV_SIZE_IN_BYTES, ciphertext.length - IV_SIZE_IN_BYTES);
}
use of javax.crypto.spec.GCMParameterSpec in project tink by google.
the class AesGcmHkdfStreaming method paramsForSegment.
private GCMParameterSpec paramsForSegment(byte[] prefix, int segmentNr, boolean last) {
ByteBuffer nonce = ByteBuffer.allocate(NONCE_SIZE_IN_BYTES);
nonce.order(ByteOrder.BIG_ENDIAN);
nonce.put(prefix);
nonce.putInt(segmentNr);
nonce.put((byte) (last ? 1 : 0));
return new GCMParameterSpec(8 * TAG_SIZE_IN_BYTES, nonce.array());
}
use of javax.crypto.spec.GCMParameterSpec in project tink by google.
the class AesGcmJce method decrypt.
@Override
public byte[] decrypt(final byte[] ciphertext, final byte[] associatedData) throws GeneralSecurityException {
if (ciphertext.length < IV_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES) {
throw new GeneralSecurityException("ciphertext too short");
}
GCMParameterSpec params = new GCMParameterSpec(8 * TAG_SIZE_IN_BYTES, ciphertext, 0, IV_SIZE_IN_BYTES);
Cipher cipher = instance();
cipher.init(Cipher.DECRYPT_MODE, keySpec, params);
if (associatedData != null && associatedData.length != 0) {
cipher.updateAAD(associatedData);
}
return cipher.doFinal(ciphertext, IV_SIZE_IN_BYTES, ciphertext.length - IV_SIZE_IN_BYTES);
}
use of javax.crypto.spec.GCMParameterSpec in project wycheproof by google.
the class AesGcmTest method testByteBufferShiftedAlias.
/**
* Encryption with ByteBuffers should be copy-safe even if the buffers have different starting
* offsets and/or do not make the backing array visible.
*
* <p>Note that bugs in this often require a sizeable input to reproduce; the default
* implementation of engineUpdate(ByteBuffer, ByteBuffer) copies through 4KB bounce buffers, so we
* need to use something larger to see any problems - 8KB is what we use here.
*
* @see https://bugs.openjdk.java.net/browse/JDK-8181386
*/
@NoPresubmitTest(providers = { ProviderType.BOUNCY_CASTLE, ProviderType.OPENJDK }, bugs = { "b/64378943" })
@Test
public void testByteBufferShiftedAlias() throws Exception {
byte[] ptVector = new byte[8192];
for (int i = 0; i < 3; i++) {
// outputOffset = offset relative to start of input.
for (int outputOffset = -1; outputOffset <= 1; outputOffset++) {
SecretKeySpec key = new SecretKeySpec(new byte[16], "AES");
GCMParameterSpec parameters = new GCMParameterSpec(128, new byte[12]);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, parameters);
ByteBuffer output, input, inputRO;
// We'll try three scenarios: Ordinary array backed buffers, array backed buffers where one
// is read-only, and direct byte buffers.
String mode;
// offsets relative to start of buffer
int inputOffsetInBuffer = 1;
int outputOffsetInBuffer = inputOffsetInBuffer + outputOffset;
int sliceLength = cipher.getOutputSize(ptVector.length);
int bufferSize = sliceLength + Math.max(inputOffsetInBuffer, outputOffsetInBuffer);
switch(i) {
case 0:
case 1:
{
byte[] buffer = new byte[bufferSize];
// It's important to slice() here as otherwise later when we flip() position will be
// reset to 0.
output = ByteBuffer.wrap(buffer, outputOffsetInBuffer, sliceLength).slice();
input = ByteBuffer.wrap(buffer, inputOffsetInBuffer, sliceLength).slice();
if (i == 1) {
mode = "array backed buffers with RO buffer";
inputRO = input.asReadOnlyBuffer();
} else {
mode = "array backed buffers";
inputRO = input.duplicate();
}
break;
}
case 2:
{
mode = "direct buffers";
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize);
output = buf.duplicate();
output.position(outputOffsetInBuffer);
output.limit(sliceLength + outputOffsetInBuffer);
output = output.slice();
input = buf.duplicate();
input.position(inputOffsetInBuffer);
input.limit(sliceLength + inputOffsetInBuffer);
input = input.slice();
inputRO = input.duplicate();
break;
}
default:
{
throw new AssertionError("Unknown test index " + i);
}
}
// Now that we have our overlapping 'input' and 'output' buffers, we can write our plaintext
// into the input buffer.
input.put(ptVector);
input.flip();
// Make sure the RO input buffer has the same limit in case the plaintext is shorter than
// sliceLength (which it generally will be for anything other than ECB or CTR mode)
inputRO.limit(input.limit());
try {
int ctSize = cipher.doFinal(inputRO, output);
// Now flip the buffers around and undo everything
byte[] tmp = new byte[ctSize];
output.flip();
output.get(tmp);
output.clear();
input.clear();
inputRO.clear();
input.put(tmp);
input.flip();
inputRO.limit(input.limit());
cipher.init(Cipher.DECRYPT_MODE, key, parameters);
cipher.doFinal(inputRO, output);
output.flip();
assertEquals(ByteBuffer.wrap(ptVector), output);
} catch (Throwable t) {
throw new AssertionError("Overlapping buffers test failed with buffer type: " + mode + " and output offset " + outputOffset, t);
}
}
}
}
use of javax.crypto.spec.GCMParameterSpec in project wycheproof by google.
the class AesGcmTest method testEncryptEmptyPlaintextWithEmptyIv.
/**
* AES-GCM allows IVs of bit length 1 .. 2^64-1. See NIST SP 800 38d, Section 5.2.1.1
* http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
*
* <p>Disallowing IVs of length 0 is necessary for the following reason: if an empty IV is used
* then the tag is an evaluation of a polynomial with the hash subkey as the value. Since the
* polynomial can be derived from the ciphertext it is known to an attacker. Therefore, any
* message encrypted with an empty IV leaks the hash subkey. In particular, encrypting an empty
* plaintext with an empty IV results in a ciphertext having a tag that is equal to the hash
* subkey used in AES-GCM. I.e. both are the same as encrypting an all zero block.
*
* <p>OpenJDK fails this test.
*/
@NoPresubmitTest(providers = { ProviderType.OPENJDK }, bugs = { "b/35746778" })
@Test
public void testEncryptEmptyPlaintextWithEmptyIv() throws Exception {
byte[] emptyIv = new byte[0];
byte[] input = new byte[0];
byte[] key = TestUtil.hexToBytes("56aae7bd5cbefc71d31c4338e6ddd6c5");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
Cipher block = Cipher.getInstance("AES/ECB/NoPadding");
block.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] hashkey = block.doFinal(new byte[16]);
try {
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new GCMParameterSpec(16 * 8, emptyIv));
byte[] ct = cipher.doFinal(input);
// If the encryption above is not rejected then the hash key and the ciphertext are the same.
// Both are d1bdd948ddc5a7f7a9250cf78229b84d.
System.out.println("testEncryptEmptyPlaintextWithEmptyIv:");
System.out.println("Encrypt with empty IV:" + TestUtil.bytesToHex(ct));
System.out.println("Hash subkey :" + TestUtil.bytesToHex(hashkey));
fail("Encrypting with an empty IV leaks the hash subkey.");
} catch (GeneralSecurityException expected) {
System.out.println("testEncryptWithEmptyIv:" + expected.toString());
// expected behavior
}
}
Aggregations