/** * Generates a random IV and encrypts this plain text with the given key. Then attaches * a hashed MAC, which is contained in the CipherTextIvMac class. * * @param plaintext The text that will be encrypted * @param secretKeys The combined AES & HMAC keys with which to encrypt * @return a tuple of the IV, ciphertext, mac * @throws GeneralSecurityException if AES is not implemented on this system */ public static CipherTextIvMac encrypt(byte[] plaintext, SecretKeys secretKeys) throws GeneralSecurityException { byte[] iv = generateIv(); Cipher aesCipherForEncryption = Cipher.getInstance(CIPHER_TRANSFORMATION); aesCipherForEncryption.init(Cipher.ENCRYPT_MODE, secretKeys.getConfidentialityKey(), new IvParameterSpec(iv)); /* * Now we get back the IV that will actually be used. Some Android * versions do funny stuff w/ the IV, so this is to work around bugs: */ iv = aesCipherForEncryption.getIV(); byte[] byteCipherText = aesCipherForEncryption.doFinal(plaintext); byte[] ivCipherConcat = CipherTextIvMac.ivCipherConcat(iv, byteCipherText); byte[] integrityMac = generateMac(ivCipherConcat, secretKeys.getIntegrityKey()); return new CipherTextIvMac(byteCipherText, iv, integrityMac); }
/** * AES CBC decrypt. * * @param civ the cipher text, iv, and mac * @param secretKeys the AES & HMAC keys * @return The raw decrypted bytes * @throws GeneralSecurityException if MACs don't match or AES is not implemented */ public static byte[] decrypt(CipherTextIvMac civ, SecretKeys secretKeys) throws GeneralSecurityException { byte[] ivCipherConcat = CipherTextIvMac.ivCipherConcat(civ.getIv(), civ.getCipherText()); byte[] computedMac = generateMac(ivCipherConcat, secretKeys.getIntegrityKey()); if (constantTimeEq(computedMac, civ.getMac())) { Cipher aesCipherForDecryption = Cipher.getInstance(CIPHER_TRANSFORMATION); aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secretKeys.getConfidentialityKey(), new IvParameterSpec(civ.getIv())); return aesCipherForDecryption.doFinal(civ.getCipherText()); } else { throw new GeneralSecurityException("MAC stored in civ does not match computed MAC."); } }
/** * return true is the supplied key is a valid aes key * * @param key * @return */ public static boolean validateKey(final AesCbcWithIntegrity.SecretKeys key) { try { String src = "abcdefghijklmopqrstuvwxyz123567890!@#$%^&*()_+{}|:\">?<,"; CipherTextIvMac encrypt = AesCbcWithIntegrity.encrypt(src, key); String decrypt = AesCbcWithIntegrity.decryptString(encrypt, key); return decrypt.equals(src) && !src.equals(encrypt.toString()); } catch (Throwable ex) { return false; } }
public static String DE(final String ciphertext, final String key) throws Exception { AesCbcWithIntegrity.SecretKeys skey = AesCbcWithIntegrity.keys(key); AesCbcWithIntegrity.CipherTextIvMac civ = new AesCbcWithIntegrity.CipherTextIvMac(ciphertext); return AesCbcWithIntegrity.decryptString(civ, skey); }
public static String EN(final String cleartext, final String key) throws Exception { AesCbcWithIntegrity.SecretKeys skey = AesCbcWithIntegrity.keys(key); AesCbcWithIntegrity.CipherTextIvMac encrypt = AesCbcWithIntegrity.encrypt(cleartext, skey); return encrypt.toString(); }