private byte[] process(AEADBlockCipher blockCipher, byte[] in) { byte[] buf = new byte[blockCipher.getOutputSize(in.length)]; int bytesWritten = blockCipher.processBytes(in, 0, in.length, buf, 0); try { bytesWritten += blockCipher.doFinal(buf, bytesWritten); } catch (InvalidCipherTextException e) { throw new IllegalStateException("unable to encrypt/decrypt", e); } if (bytesWritten == buf.length) { return buf; } byte[] out = new byte[bytesWritten]; System.arraycopy(buf, 0, out, 0, bytesWritten); return out; }
@Override public InputStream newCipherInputStream(InputStream underlyingInputStream, byte[] secretKey, byte[] iv) throws CipherException { AEADBlockCipher cipher = new GCMBlockCipher(new TwofishEngine()); cipher.init(false, new AEADParameters(new KeyParameter(secretKey), MAC_SIZE, iv)); return new org.bouncycastle.crypto.io.CipherInputStream(underlyingInputStream, cipher); } }
@Override public byte[] encrypt(byte[] bytes) { byte[] iv = this.ivGenerator.generateKey(); @SuppressWarnings("deprecation") GCMBlockCipher blockCipher = new GCMBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()); blockCipher.init(true, new AEADParameters(secretKey, 128, iv, null)); byte[] encrypted = process(blockCipher, bytes); return iv != null ? concatenate(iv, encrypted) : encrypted; }
private static String encrypt(byte[] key, String plainText) throws CryptoException { try { PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESEngine())); KeyParameter keyParameter = new KeyParameter(key); cipher.init(true, keyParameter); byte[] plainTextBytes = plainText.getBytes(); byte[] cipherTextBytes = new byte[cipher.getOutputSize(plainTextBytes.length)]; int outputLength = cipher.processBytes(plainTextBytes, 0, plainTextBytes.length, cipherTextBytes, 0); cipher.doFinal(cipherTextBytes, outputLength); return ENCODER.encodeToString(cipherTextBytes).trim(); } catch (Exception e) { throw new CryptoException(e); } }
System.arraycopy(authTag, 0, input, cipherText.length, authTag.length); int outputLength = cipher.getOutputSize(input.length); int outputOffset = cipher.processBytes(input, 0, input.length, output, 0); outputOffset += cipher.doFinal(output, outputOffset);
private static String decrypt(byte[] key, String cipherText) throws CryptoException { try { PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESEngine())); cipher.init(false, new KeyParameter(key)); byte[] cipherTextBytes = DECODER.decode(cipherText); byte[] plainTextBytes = new byte[cipher.getOutputSize(cipherTextBytes.length)]; int outputLength = cipher.processBytes(cipherTextBytes, 0, cipherTextBytes.length, plainTextBytes, 0); cipher.doFinal(plainTextBytes, outputLength); int paddingStarts = plainTextBytes.length - 1; for (; paddingStarts >= 0; paddingStarts--) { if (plainTextBytes[paddingStarts] != 0) { break; } } return new String(plainTextBytes, 0, paddingStarts + 1); } catch (Exception e) { throw new CryptoException(e); } }
@Override public byte[] encrypt(byte[] bytes) { byte[] iv = this.ivGenerator.generateKey(); @SuppressWarnings("deprecation") GCMBlockCipher blockCipher = new GCMBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()); blockCipher.init(true, new AEADParameters(secretKey, 128, iv, null)); byte[] encrypted = process(blockCipher, bytes); return iv != null ? concatenate(iv, encrypted) : encrypted; }
@Override public OutputStream newCipherOutputStream(OutputStream underlyingOutputStream, byte[] secretKey, byte[] iv) throws CipherException { AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); cipher.init(true, new AEADParameters(new KeyParameter(secretKey), MAC_SIZE, iv)); return new org.bouncycastle.crypto.io.CipherOutputStream(underlyingOutputStream, cipher); }
private byte[] process(AEADBlockCipher blockCipher, byte[] in) { byte[] buf = new byte[blockCipher.getOutputSize(in.length)]; int bytesWritten = blockCipher.processBytes(in, 0, in.length, buf, 0); try { bytesWritten += blockCipher.doFinal(buf, bytesWritten); } catch (InvalidCipherTextException e) { throw new IllegalStateException("unable to encrypt/decrypt", e); } if (bytesWritten == buf.length) { return buf; } byte[] out = new byte[bytesWritten]; System.arraycopy(buf, 0, out, 0, bytesWritten); return out; }
@Override public byte[] encrypt(byte[] bytes) { byte[] iv = this.ivGenerator.generateKey(); @SuppressWarnings("deprecation") PaddedBufferedBlockCipher blockCipher = new PaddedBufferedBlockCipher( new CBCBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()), new PKCS7Padding()); blockCipher.init(true, new ParametersWithIV(secretKey, iv)); byte[] encrypted = process(blockCipher, bytes); return iv != null ? concatenate(iv, encrypted) : encrypted; }
@Override public byte[] decrypt(byte[] encryptedBytes) { byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength()); encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length); @SuppressWarnings("deprecation") GCMBlockCipher blockCipher = new GCMBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()); blockCipher.init(false, new AEADParameters(secretKey, 128, iv, null)); return process(blockCipher, encryptedBytes); }
@Override public OutputStream newCipherOutputStream(OutputStream underlyingOutputStream, byte[] secretKey, byte[] iv) throws CipherException { AEADBlockCipher cipher = new GCMBlockCipher(new TwofishEngine()); cipher.init(true, new AEADParameters(new KeyParameter(secretKey), MAC_SIZE, iv)); return new org.bouncycastle.crypto.io.CipherOutputStream(underlyingOutputStream, cipher); }
@Override public byte[] encrypt(byte[] bytes) { byte[] iv = this.ivGenerator.generateKey(); @SuppressWarnings("deprecation") PaddedBufferedBlockCipher blockCipher = new PaddedBufferedBlockCipher( new CBCBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()), new PKCS7Padding()); blockCipher.init(true, new ParametersWithIV(secretKey, iv)); byte[] encrypted = process(blockCipher, bytes); return iv != null ? concatenate(iv, encrypted) : encrypted; }
@Override public byte[] decrypt(byte[] encryptedBytes) { byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength()); encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length); @SuppressWarnings("deprecation") GCMBlockCipher blockCipher = new GCMBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()); blockCipher.init(false, new AEADParameters(secretKey, 128, iv, null)); return process(blockCipher, encryptedBytes); }
@Override public InputStream newCipherInputStream(InputStream underlyingInputStream, byte[] secretKey, byte[] iv) throws CipherException { AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); cipher.init(false, new AEADParameters(new KeyParameter(secretKey), MAC_SIZE, iv)); return new org.bouncycastle.crypto.io.CipherInputStream(underlyingInputStream, cipher); } }
@Override public byte[] decrypt(byte[] encryptedBytes) { byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength()); encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length); @SuppressWarnings("deprecation") PaddedBufferedBlockCipher blockCipher = new PaddedBufferedBlockCipher( new CBCBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()), new PKCS7Padding()); blockCipher.init(false, new ParametersWithIV(secretKey, iv)); return process(blockCipher, encryptedBytes); }
/** * Creates a new AES/GCM/NoPadding cipher. * * @param secretKey The AES key. Must not be {@code null}. * @param forEncryption If {@code true} creates an encryption cipher, * else creates a decryption cipher. * @param iv The initialisation vector (IV). Must not be * {@code null}. * @param authData The authenticated data. Must not be * {@code null}. * * @return The AES/GCM/NoPadding cipher. */ private static GCMBlockCipher createAESGCMCipher(final SecretKey secretKey, final boolean forEncryption, final byte[] iv, final byte[] authData) { // Initialise AES cipher BlockCipher cipher = AES.createCipher(secretKey, forEncryption); // Create GCM cipher with AES GCMBlockCipher gcm = new GCMBlockCipher(cipher); AEADParameters aeadParams = new AEADParameters(new KeyParameter(secretKey.getEncoded()), AUTH_TAG_BIT_LENGTH, iv, authData); gcm.init(forEncryption, aeadParams); return gcm; }
@Test public void testE_BouncyCastleCipherInputStreamWithAesGcmLongPlaintext() throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { // Encrypt (not interesting in this example) byte[] randomKey = createRandomArray(16); byte[] randomIv = createRandomArray(16); byte[] originalPlaintext = createRandomArray(4080); // <<<< 4080 bytes fails, 4079 bytes works! byte[] originalCiphertext = encryptWithAesGcm(originalPlaintext, randomKey, randomIv); // Decrypt with BouncyCastle implementation of CipherInputStream AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); cipher.init(false, new AEADParameters(new KeyParameter(randomKey), 128, randomIv)); try { readFromStream(new org.bouncycastle.crypto.io.CipherInputStream(new ByteArrayInputStream(originalCiphertext), cipher)); // ^^^^^^^^^^^^^^^ INTERESTING PART ^^^^^^^^^^^^^^^^ // // In this example, the BouncyCastle implementation of the CipherInputStream throws an ArrayIndexOutOfBoundsException. // The only difference to the example above is that the plaintext is now 4080 bytes long! For 4079 bytes plaintexts, // everything works just fine. System.out.println("Test E: org.bouncycastle.crypto.io.CipherInputStream: OK, throws no exception"); } catch (IOException e) { fail("Test E: org.bouncycastle.crypto.io.CipherInputStream: NOT OK throws: "+e.getMessage()); } }
@Override public byte[] decrypt(byte[] encryptedBytes) { byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength()); encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length); @SuppressWarnings("deprecation") PaddedBufferedBlockCipher blockCipher = new PaddedBufferedBlockCipher( new CBCBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()), new PKCS7Padding()); blockCipher.init(false, new ParametersWithIV(secretKey, iv)); return process(blockCipher, encryptedBytes); }
AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); cipher.init(false, new AEADParameters(new KeyParameter(randomKey), 128, randomIv));