我曾尝试在Nexus 5中运行以下AES/CBC/PKCS5Padding加密和解密代码,并将SHA-1作为 key 生成。它到目前为止运行良好。
但是,我唯一关心的是,所有类型的Android设备上都可以使用AES/CBC/PKCS5Padding加密解密算法和SHA-1哈希算法吗?
以下代码是否有可能无法在某些Android设备上运行?如果是这样,是否有任何后备计划?
AES/CBC/PKCS5填充
// http://stackoverflow.com/questions/3451670/java-aes-and-using-my-own-key
public static byte[] generateKey(String key) throws GeneralSecurityException, UnsupportedEncodingException {
byte[] binary = key.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
binary = sha.digest(binary);
// Use only first 128 bit.
binary = Arrays.copyOf(binary, 16);
return binary;
}
// http://stackoverflow.com/questions/17322002/what-causes-the-error-java-security-invalidkeyexception-parameters-missing
public static String encrypt(byte[] key, String value) throws GeneralSecurityException {
// Argument validation.
if (key.length != 16) {
throw new IllegalArgumentException("Invalid key size.");
}
// Setup AES tool.
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
// Do the job with AES tool.
byte[] original = value.getBytes(Charset.forName("UTF-8"));
byte[] binary = cipher.doFinal(original);
return Base64.encodeToString(binary, Base64.DEFAULT);
}
// // http://stackoverflow.com/questions/17322002/what-causes-the-error-java-security-invalidkeyexception-parameters-missing
public static String decrypt(byte[] key, String encrypted) throws GeneralSecurityException {
// Argument validation.
if (key.length != 16) {
throw new IllegalArgumentException("Invalid key size.");
}
// Setup AES tool.
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
// Do the job with AES tool.
byte[] binary = Base64.decode(encrypted, Base64.DEFAULT);
byte[] original = cipher.doFinal(binary);
return new String(original, Charset.forName("UTF-8"));
}
用法
byte[] key = generateKey("my secret key");
String ciphertext = encrypt(key, "my plain content");
String plainContent = decrypt(key, ciphertext);
最佳答案
不,它不太可能会失败。 Android API是从Java API派生的。自1.4版以来,Java API已包含"AES/CBC/PKCS5Padding"
。
至于"SHA-1"
,这是一个更老的算法,自从开始以来就受到支持。
当心不要使用"PKCS7Padding"
代替。 Java使用"PKCS5Padding"
来代替,即使含义相同,对"PKCS7Padding"
的支持也可能是粗略的。
请注意,您应该使用基于密码的加密(PBE)代替AES/CBC和SHA-1。特别是使用SHA-1作为 key 派生方法特别危险,因为您不使用盐或工作因数,因为基于密码的 key 派生功能(如PBKDF2)应该是很好的。基本上,只有在您知道密码包含足够的熵的情况下,才执行此操作。
但是,对于同一个键使用全零的IV会更糟(如注释中已指出的那样)。它使攻击者可以找到重复的(纯文本输入)(起始块)。始终建议使用经过身份验证的加密(例如使用HMAC-SHA-1),传输模式加密或多或少要求使用经过身份验证的加密(与无法进行纯文本/填充oracle攻击的就地加密相反)。