解决方案
- Kotlin版
object AesCryptUtil {
private const val AES_MODE = "AES/CBC/PKCS7Padding"
private const val CHARSET = "UTF-8"
private const val CIPHER = "AES"
private const val HASH_ALGORITHM = "SHA-256"
private val IV_BYTES = byteArrayOf(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
/**
* Generates SHA256 hash of the password which is used as key
*
* @param password used to generated key
* @return SHA256 of the password
*/
@Throws(NoSuchAlgorithmException::class, UnsupportedEncodingException::class)
private fun generateKey(password: String): SecretKeySpec {
val digest = MessageDigest.getInstance(HASH_ALGORITHM)
val bytes = password.toByteArray(charset(CHARSET))
digest.update(bytes, 0, bytes.size)
val key = digest.digest()
return SecretKeySpec(key, CIPHER)
}
/**
* Encrypt and encode message using 256-bit AES with key generated from password.
*
* @param password used to generated key
* @param message the thing you want to encrypt assumed String UTF-8
* @return Base64 encoded CipherText
* @throws GeneralSecurityException if problems occur during encryption
*/
@Throws(GeneralSecurityException::class)
fun encrypt(password: String, message: String): String {
try {
val key = generateKey(password)
val cipherText = encrypt(key, IV_BYTES, message.toByteArray(charset(CHARSET)))
//NO_WRAP is important as was getting \n at the end
return Base64.encodeToString(cipherText, Base64.NO_WRAP)
} catch (e: UnsupportedEncodingException) {
throw GeneralSecurityException(e)
}
}
/**
* More flexible AES encrypt that doesn't encode
*
* @param key AES key typically 128, 192 or 256 bit
* @param iv Initiation Vector
* @param message in bytes (assumed it's already been decoded)
* @return Encrypted cipher text (not encoded)
* @throws GeneralSecurityException if something goes wrong during encryption
*/
@Throws(GeneralSecurityException::class)
fun encrypt(key: SecretKeySpec, iv: ByteArray, message: ByteArray): ByteArray {
val cipher = Cipher.getInstance(AES_MODE)
val ivSpec = IvParameterSpec(iv)
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec)
return cipher.doFinal(message)
}
/**
* Decrypt and decode ciphertext using 256-bit AES with key generated from password
*
* @param password used to generated key
* @param base64EncodedCipherText the encrpyted message encoded with base64
* @return message in Plain text (String UTF-8)
* @throws GeneralSecurityException if there's an issue decrypting
*/
@Throws(GeneralSecurityException::class)
fun decrypt(password: String, base64EncodedCipherText: String): String {
try {
val key = generateKey(password)
val decodedCipherText = Base64.decode(base64EncodedCipherText, Base64.NO_WRAP)
val decryptedBytes = decrypt(key, IV_BYTES, decodedCipherText)
return String(decryptedBytes, charset(CHARSET))
} catch (e: UnsupportedEncodingException) {
throw GeneralSecurityException(e)
}
}
/**
* More flexible AES decrypt that doesn't encode
*
* @param key AES key typically 128, 192 or 256 bit
* @param iv Initiation Vector
* @param decodedCipherText in bytes (assumed it's already been decoded)
* @return Decrypted message cipher text (not encoded)
* @throws GeneralSecurityException if something goes wrong during encryption
*/
@Throws(GeneralSecurityException::class)
fun decrypt(key: SecretKeySpec, iv: ByteArray, decodedCipherText: ByteArray): ByteArray {
val cipher = Cipher.getInstance(AES_MODE)
val ivSpec = IvParameterSpec(iv)
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec)
return cipher.doFinal(decodedCipherText)
}
}
- Java版
public final class AesCryptUtil {
private static final String AES_MODE = "AES/CBC/PKCS7Padding";
private static final String CHARSET = "UTF-8";
private static final String CIPHER = "AES";
private static final String HASH_ALGORITHM = "SHA-256";
private static final byte[] IV_BYTES = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/**
* Generates SHA256 hash of the password which is used as key
*
* @param password used to generated key
* @return SHA256 of the password
*/
private static SecretKeySpec generateKey(final String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
byte[] bytes = password.getBytes(CHARSET);
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
return new SecretKeySpec(key, CIPHER);
}
/**
* Encrypt and encode message using 256-bit AES with key generated from password.
*
* @param password used to generated key
* @param message the thing you want to encrypt assumed String UTF-8
* @return Base64 encoded CipherText
* @throws GeneralSecurityException if problems occur during encryption
*/
public static String encrypt(final String password, String message)
throws GeneralSecurityException {
try {
final SecretKeySpec key = generateKey(password);
byte[] cipherText = encrypt(key, IV_BYTES, message.getBytes(CHARSET));
//NO_WRAP is important as was getting \n at the end
return Base64.encodeToString(cipherText, Base64.NO_WRAP);
} catch (UnsupportedEncodingException e) {
throw new GeneralSecurityException(e);
}
}
/**
* More flexible AES encrypt that doesn't encode
*
* @param key AES key typically 128, 192 or 256 bit
* @param iv Initiation Vector
* @param message in bytes (assumed it's already been decoded)
* @return Encrypted cipher text (not encoded)
* @throws GeneralSecurityException if something goes wrong during encryption
*/
public static byte[] encrypt(final SecretKeySpec key, final byte[] iv, final byte[] message)
throws GeneralSecurityException {
final Cipher cipher = Cipher.getInstance(AES_MODE);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
return cipher.doFinal(message);
}
/**
* Decrypt and decode ciphertext using 256-bit AES with key generated from password
*
* @param password used to generated key
* @param base64EncodedCipherText the encrpyted message encoded with base64
* @return message in Plain text (String UTF-8)
* @throws GeneralSecurityException if there's an issue decrypting
*/
public static String decrypt(final String password, String base64EncodedCipherText)
throws GeneralSecurityException {
try {
final SecretKeySpec key = generateKey(password);
byte[] decodedCipherText = Base64.decode(base64EncodedCipherText, Base64.NO_WRAP);
byte[] decryptedBytes = decrypt(key, IV_BYTES, decodedCipherText);
return new String(decryptedBytes, CHARSET);
} catch (UnsupportedEncodingException e) {
throw new GeneralSecurityException(e);
}
}
/**
* More flexible AES decrypt that doesn't encode
*
* @param key AES key typically 128, 192 or 256 bit
* @param iv Initiation Vector
* @param decodedCipherText in bytes (assumed it's already been decoded)
* @return Decrypted message cipher text (not encoded)
* @throws GeneralSecurityException if something goes wrong during encryption
*/
public static byte[] decrypt(final SecretKeySpec key, final byte[] iv, final byte[] decodedCipherText)
throws GeneralSecurityException {
final Cipher cipher = Cipher.getInstance(AES_MODE);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
return cipher.doFinal(decodedCipherText);
}
}
调用样例:
- 加密
val encryptedStr = AesCryptUtil.encrypt("123456","程序园中猿的多彩生活")
- 解密
val decryptedStr = AesCryptUtil.decrypt("123456",encryptedStr)
Demo源代码
https://github.com/cxyzy1/AESCrypt
安卓开发技术分享: https://blog.csdn.net/yinxing2008/article/details/84555061 点击关注专栏,查看最新技术分享 更多技术总结好文,请关注:「程序园中猿」