byte[] mac = new byte[NigoriConstants.B_MAC];
Cipher cipher;
try {
cipher = Cipher.getInstance(NigoriConstants.A_SYMENC_CIPHER);
} catch (NoSuchPaddingException e) {
throw new NigoriCryptographyException(e);
} catch (NoSuchAlgorithmException e) {
throw new NigoriCryptographyException(e);
}
if (ciphertext.length < iv.length + mac.length + cipher.getBlockSize()) {
throw new NigoriCryptographyException(
"Ciphertext is too short to be a valid encrypted message.");
}
byte[] data = new byte[ciphertext.length - iv.length - mac.length];
System.arraycopy(ciphertext, 0, iv, 0, iv.length);
System.arraycopy(ciphertext, ciphertext.length - mac.length, mac, 0, mac.length);
System.arraycopy(ciphertext, iv.length, data, 0, data.length);
byte[] macCheck = generateCipherHMAC(data);
if (mac.length != macCheck.length) {
throw new NigoriCryptographyException(String.format(
"Length mismatch between provided (%d) and received (%d) HMACs.", mac.length,
macCheck.length));
}
for (int i = 0; i < macCheck.length; i++) {
if (mac[i] != macCheck[i]) {
throw new NigoriCryptographyException("HMAC of ciphertext does not match expected value");
}
}
try {
SecretKey key = new SecretKeySpec(encryptionKey, NigoriConstants.A_SYMENC);
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(data);
} catch (InvalidAlgorithmParameterException e) {
throw new NigoriCryptographyException(e);
} catch (InvalidKeyException e) {
throw new NigoriCryptographyException(e);
} catch (BadPaddingException e) {
throw new NigoriCryptographyException(e);
} catch (IllegalBlockSizeException e) {
throw new NigoriCryptographyException(e);
}
}