问题
Here's a sample dummy code called test(), I run this 100K times and I get different encrypted messages for the same plain text (obviously, the decryption I get is the original plain text).
I guess the reason behind this is to avoid frequency; but how come there can be MANY encryption to ONE decryption? shouldn't it be a one to one?
public static void test()
{
String plainMessage = "I'm gonna bid 100 USD on this project";
String password = "A99922000001000004581F0F0CCD0000";
Set<String> set = new HashSet<String>();
for (int x=0; x<100000; x++)
{
String enc = AESEncryption.encryptMessage(plainMessage, password);
System.out.println(enc);
set.add(enc);
String dec = AESEncryption.decryptMessage(enc, password);
if (!dec.equals(plainMessage))
{
System.out.println("wrong decryption"); //never gets here
break;
}
}
System.out.println(">"+set.size()); //just to make sure they are all unique
}
the encryption
public static String encryptMessage(final String plainMessage, final String symKeyHex)
{
final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);
final byte[] encodedMessage = plainMessage.getBytes(Charset.forName("UTF-8"));
try {
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
final int blockSize = cipher.getBlockSize();
// create the key
final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");
// generate random IV using block size (possibly create a method for
// this)
final byte[] ivData = new byte[blockSize];
final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
rnd.nextBytes(ivData);
final IvParameterSpec iv = new IvParameterSpec(ivData);
cipher.init(Cipher.ENCRYPT_MODE, symKey, iv);
final byte[] encryptedMessage = cipher.doFinal(encodedMessage);
// concatenate IV and encrypted message
final byte[] ivAndEncryptedMessage = new byte[ivData.length + encryptedMessage.length];
System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage, blockSize, encryptedMessage.length);
final String ivAndEncryptedMessageBase64 = DatatypeConverter.printBase64Binary(ivAndEncryptedMessage);
return ivAndEncryptedMessageBase64;
}catch (InvalidKeyException e)
{
throw new IllegalArgumentException("key argument does not contain a valid AES key");
}catch (GeneralSecurityException e)
{
throw new IllegalStateException("Unexpected exception during encryption", e);
}
}
回答1:
To add some clarity to the comments:
The iv or initialization vector is like a second key which is used to encrypt the data.
Since you use a random iv each time (this is good), you get different encrypted text each time. This second key is actually included with the encrypted text, so you don't need to pass it along separately.
Having just the iv doesn't enable you to crack the encryption (which is why you can pass it along with the encrypted text), but by using it, you can send the same plain text with the same password multiple times (using different ivs) and get completely different encrypted values.
来源:https://stackoverflow.com/questions/24701068/what-makes-aes-with-base64-generate-different-encryption-result-for-the-same-pla