/** * AES CBC decrypt. * * @param civ The cipher text, IV, and mac * @param secretKeys The AES & HMAC keys * @param encoding The string encoding to use to decode the bytes after decryption * @return A string derived from the decrypted bytes (not base64 encoded) * @throws GeneralSecurityException if AES is not implemented on this system * @throws UnsupportedEncodingException if the encoding is unsupported */ public static String decryptString(CipherTextIvMac civ, SecretKeys secretKeys, String encoding) throws UnsupportedEncodingException, GeneralSecurityException { return new String(decrypt(civ, secretKeys), encoding); }
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); }
/** * 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; } }
/** * A function that generates random AES & HMAC keys and prints out exceptions but * doesn't throw them since none should be encountered. If they are * encountered, the return value is null. * * @return The AES & HMAC keys. * @throws GeneralSecurityException if AES is not implemented on this system, * or a suitable RNG is not available */ public static SecretKeys generateKey() throws GeneralSecurityException { fixPrng(); KeyGenerator keyGen = KeyGenerator.getInstance(CIPHER); // No need to provide a SecureRandom or set a seed since that will // happen automatically. keyGen.init(AES_KEY_LENGTH_BITS); SecretKey confidentialityKey = keyGen.generateKey(); //Now make the HMAC key byte[] integrityKeyBytes = randomBytes(HMAC_KEY_LENGTH_BITS / 8);//to get bytes SecretKey integrityKey = new SecretKeySpec(integrityKeyBytes, HMAC_ALGORITHM); return new SecretKeys(confidentialityKey, integrityKey); }
/** * A function that generates password-based AES & HMAC keys. It prints out exceptions but * doesn't throw them since none should be encountered. If they are * encountered, the return value is null. * * @param password The password to derive the keys from. * @return The AES & HMAC keys. * @throws GeneralSecurityException if AES is not implemented on this system, * or a suitable RNG is not available */ public static SecretKeys generateKeyFromPassword(String password, byte[] salt) throws GeneralSecurityException { fixPrng(); //Get enough random bytes for both the AES key and the HMAC key: KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, PBE_ITERATION_COUNT, AES_KEY_LENGTH_BITS + HMAC_KEY_LENGTH_BITS); SecretKeyFactory keyFactory = SecretKeyFactory .getInstance(PBE_ALGORITHM); byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); // Split the random bytes into two parts: byte[] confidentialityKeyBytes = copyOfRange(keyBytes, 0, AES_KEY_LENGTH_BITS /8); byte[] integrityKeyBytes = copyOfRange(keyBytes, AES_KEY_LENGTH_BITS /8, AES_KEY_LENGTH_BITS /8 + HMAC_KEY_LENGTH_BITS /8); //Generate the AES key SecretKey confidentialityKey = new SecretKeySpec(confidentialityKeyBytes, CIPHER); //Generate the HMAC key SecretKey integrityKey = new SecretKeySpec(integrityKeyBytes, HMAC_ALGORITHM); return new SecretKeys(confidentialityKey, integrityKey); }
/** * 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."); } }
/** * 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, which * will be serialized with UTF-8 * @param secretKeys The 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 * @throws UnsupportedEncodingException if UTF-8 is not supported in this system */ public static CipherTextIvMac encrypt(String plaintext, SecretKeys secretKeys) throws UnsupportedEncodingException, GeneralSecurityException { return encrypt(plaintext, secretKeys, "UTF-8"); }
/** * AES CBC decrypt. * * @param civ The cipher text, IV, and mac * @param secretKeys The AES & HMAC keys * @return A string derived from the decrypted bytes, which are interpreted * as a UTF-8 String * @throws GeneralSecurityException if AES is not implemented on this system * @throws UnsupportedEncodingException if UTF-8 is not supported */ public static String decryptString(CipherTextIvMac civ, SecretKeys secretKeys) throws UnsupportedEncodingException, GeneralSecurityException { return decryptString(civ, secretKeys, "UTF-8"); }
private static byte[] randomBytes(int length) throws GeneralSecurityException { fixPrng(); SecureRandom random = new SecureRandom(); byte[] b = new byte[length]; random.nextBytes(b); return b; }
/** * A function that generates password-based AES & HMAC keys. See generateKeyFromPassword. * @param password The password to derive the AES/HMAC keys from * @param salt A string version of the salt; base64 encoded. * @return The AES & HMAC keys. * @throws GeneralSecurityException */ public static SecretKeys generateKeyFromPassword(String password, String salt) throws GeneralSecurityException { return generateKeyFromPassword(password, Base64.decodeBase64(salt)); }
/** * Generate a new AES 256 bit encryption key. Once generated, this key can * be used to replace the default key. * * @param keysize must be a supported key size, using 128 or 256 * @return */ public static String GEN(final short keysize) { try { return AesCbcWithIntegrity.generateKey().toString(); } catch (GeneralSecurityException ex) { log.log(Level.ERROR, "There was an error generating key, this could indicate that you're making a 256 bit key on a system that does not have the Java Crypto Extensions installed. . Is JCE installed? " + (isJCEInstalled ? "yes " : "no ") + ex.getMessage()); log.log(Level.DEBUG, "error generating key, this could indicate that you're making a 256 bit key on a system that does not have the Java Crypto Extensions installed. " + ex.getMessage(), ex); } return null; }
/** * 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 bytes that will be encrypted * @param secretKeys The 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 * @throws UnsupportedEncodingException if the specified encoding is invalid */ public static CipherTextIvMac encrypt(String plaintext, SecretKeys secretKeys, String encoding) throws UnsupportedEncodingException, GeneralSecurityException { return encrypt(plaintext.getBytes(encoding), secretKeys); }