Android AES(带密钥库)使用相同的明文生成不同的密文
Android AES (with Keystore) produces different cipher text with same plain text
我正在尝试让 Keystore 帮助我生成用于 AES 加密的密钥,并用它来加密我输入的纯文本。这是我的代码。我在另一个activity的onCreate()方法中只调用了一次createKey()方法,然后使用相同的keyAlias和相同的明文多次调用printCipherText()方法。奇怪的是:每次调用 printCipherText() 方法时,我都会得到不同的结果。我使用相同的密钥别名和相同的明文,但为什么每次都得到不同的密文?
public class KeyCreatorClass {
KeyStore keyStore;
KeyGenerator keyGenerator;
Cipher cipher;
public void createKey(String keyAlias) { //I call this method only once in the onCreate() method of another activity, with keyAlias "A"
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
keyStore.load(null);
keyGenerator.init(
new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(false)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setRandomizedEncryptionRequired(false)
.build());
keyGenerator.generateKey();
} catch (Exception e) {
e.printStackTrace();
}
}
public String printCipherText(String keyAlias, String plainText){ //I call this method many times with the same keyAlias "A" and same plaintext in the same activity
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(keyAlias, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return byteToHex(cipher.doFinal(plainText.getBytes()));
}catch(Exception e){
e.printStackTrace();
}
return "BUG";
}
private String byteToHex(byte[] byteArray){
StringBuilder buf = new StringBuilder();
for (byte b : byteArray)
buf.append(String.format("%02X", b));
String hexStr = buf.toString();
return hexStr;
}
}
您正在使用使用初始化向量 (IV) 的 CBC 模式。由于您没有在代码中指定 IV,因此每次调用代码时都会随机生成它。这是一个重要的 属性 以防止密文观察者确定是否有您再次发送的消息。这是实现语义安全所必需的。
由于 IV 是随机生成的,因此您需要在加密期间和解密期间使用的相同 IV。 IV 不必是秘密的,但它必须是不可预测的(确实如此)。一种常见的方式是写在密文前面,解密时再读回来。它始终具有相同的长度,即块大小。对于 AES,该大小为 16 字节。
我正在尝试让 Keystore 帮助我生成用于 AES 加密的密钥,并用它来加密我输入的纯文本。这是我的代码。我在另一个activity的onCreate()方法中只调用了一次createKey()方法,然后使用相同的keyAlias和相同的明文多次调用printCipherText()方法。奇怪的是:每次调用 printCipherText() 方法时,我都会得到不同的结果。我使用相同的密钥别名和相同的明文,但为什么每次都得到不同的密文?
public class KeyCreatorClass {
KeyStore keyStore;
KeyGenerator keyGenerator;
Cipher cipher;
public void createKey(String keyAlias) { //I call this method only once in the onCreate() method of another activity, with keyAlias "A"
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
keyStore.load(null);
keyGenerator.init(
new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(false)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setRandomizedEncryptionRequired(false)
.build());
keyGenerator.generateKey();
} catch (Exception e) {
e.printStackTrace();
}
}
public String printCipherText(String keyAlias, String plainText){ //I call this method many times with the same keyAlias "A" and same plaintext in the same activity
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(keyAlias, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return byteToHex(cipher.doFinal(plainText.getBytes()));
}catch(Exception e){
e.printStackTrace();
}
return "BUG";
}
private String byteToHex(byte[] byteArray){
StringBuilder buf = new StringBuilder();
for (byte b : byteArray)
buf.append(String.format("%02X", b));
String hexStr = buf.toString();
return hexStr;
}
}
您正在使用使用初始化向量 (IV) 的 CBC 模式。由于您没有在代码中指定 IV,因此每次调用代码时都会随机生成它。这是一个重要的 属性 以防止密文观察者确定是否有您再次发送的消息。这是实现语义安全所必需的。
由于 IV 是随机生成的,因此您需要在加密期间和解密期间使用的相同 IV。 IV 不必是秘密的,但它必须是不可预测的(确实如此)。一种常见的方式是写在密文前面,解密时再读回来。它始终具有相同的长度,即块大小。对于 AES,该大小为 16 字节。