use of org.bouncycastle.crypto.engines.AESEngine in project inbot-utils by Inbot.
the class AESUtils method decryptBouncyCastle.
private static String decryptBouncyCastle(SecretKey secret, String input) {
try {
// Convert url-safe base64 to normal base64, remove carriage returns
input = input.replaceAll("-", "+").replaceAll("_", "/").replaceAll("\r", "").replaceAll("\n", "");
String[] splitInput = SPLIT_PATTERN.split(input);
byte[] iv = hexStringToByteArray(splitInput[0]);
byte[] encrypted = Base64.decodeBase64(splitInput[1]);
// get raw key from password and salt
byte[] key = secret.getEncoded();
// setup cipher parameters with key and IV
KeyParameter keyParam = new KeyParameter(key);
CipherParameters params = new ParametersWithIV(keyParam, iv);
// setup AES cipher in CBC mode with PKCS7 padding
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()), new PKCS7Padding());
cipher.reset();
cipher.init(false, params);
// create a temporary buffer to decode into (it'll include padding)
byte[] buf = new byte[cipher.getOutputSize(encrypted.length)];
int len = cipher.processBytes(encrypted, 0, encrypted.length, buf, 0);
len += cipher.doFinal(buf, len);
// lose the padding
byte[] out = new byte[len];
System.arraycopy(buf, 0, out, 0, len);
// lose the salt
String plaintext = new String(out, StandardCharsets.UTF_8);
String md5Hash = plaintext.substring(0, 22);
String plainTextWithoutHash = plaintext.substring(22);
if (md5Hash.equals(HashUtils.md5(plainTextWithoutHash))) {
return plainTextWithoutHash;
} else {
// it's possible to decrypt to garbage with the wrong key; the md5 check helps detecting that
throw new IllegalArgumentException("wrong aes key - incorrect content hash");
}
} catch (DataLengthException e) {
throw new IllegalStateException("buffer not big enough", e);
} catch (InvalidCipherTextException e) {
throw new IllegalArgumentException("wrong password");
}
}
use of org.bouncycastle.crypto.engines.AESEngine in project elastic-core-maven by OrdinaryDude.
the class Crypto method aesDecrypt.
public static byte[] aesDecrypt(byte[] ivCiphertext, byte[] key) {
try {
if (ivCiphertext.length < 16 || ivCiphertext.length % 16 != 0) {
throw new InvalidCipherTextException("invalid ivCiphertext length");
}
byte[] iv = Arrays.copyOfRange(ivCiphertext, 0, 16);
byte[] ciphertext = Arrays.copyOfRange(ivCiphertext, 16, ivCiphertext.length);
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
aes.init(false, ivAndKey);
byte[] output = new byte[aes.getOutputSize(ciphertext.length)];
int plaintextLength = aes.processBytes(ciphertext, 0, ciphertext.length, output, 0);
plaintextLength += aes.doFinal(output, plaintextLength);
byte[] result = new byte[plaintextLength];
System.arraycopy(output, 0, result, 0, result.length);
return result;
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
use of org.bouncycastle.crypto.engines.AESEngine in project syncany by syncany.
the class AesGcmCipherSpec method newCipherOutputStream.
@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);
}
use of org.bouncycastle.crypto.engines.AESEngine in project syncany by syncany.
the class AesGcmWithBcInputStreamTest method testE_BouncyCastleCipherInputStreamWithAesGcmLongPlaintext.
@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);
// <<<< 4080 bytes fails, 4079 bytes works!
byte[] originalPlaintext = createRandomArray(4080);
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());
}
}
use of org.bouncycastle.crypto.engines.AESEngine in project syncany by syncany.
the class AesGcmWithBcInputStreamTest method testD_BouncyCastleCipherInputStreamWithAesGcm.
@Test
public void testD_BouncyCastleCipherInputStreamWithAesGcm() throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
// Encrypt (not interesting in this example)
byte[] randomKey = createRandomArray(16);
byte[] randomIv = createRandomArray(16);
byte[] originalPlaintext = "Confirm 100$ pay".getBytes("ASCII");
byte[] originalCiphertext = encryptWithAesGcm(originalPlaintext, randomKey, randomIv);
// Attack / alter ciphertext (an attacker would do this!)
byte[] alteredCiphertext = Arrays.clone(originalCiphertext);
// <<< Change 100$ to 900$
alteredCiphertext[8] = (byte) (alteredCiphertext[8] ^ 0x08);
// 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(alteredCiphertext), cipher));
// ^^^^^^^^^^^^^^^ INTERESTING PART ^^^^^^^^^^^^^^^^
//
// The BouncyCastle implementation of the CipherInputStream detects MAC verification errors and
// throws a InvalidCipherTextIOException if an error occurs. Nice! A more or less minor issue
// however is that it is incompatible with the standard JCE Cipher class from the javax.crypto
// package. The new interface AEADBlockCipher must be used. The code below is not executed.
fail("Test D: org.bouncycastle.crypto.io.CipherInputStream: NOT OK, tampering not detected");
} catch (InvalidCipherTextIOException e) {
System.out.println("Test D: org.bouncycastle.crypto.io.CipherInputStream: OK, tampering detected");
}
}
Aggregations