Android:使用带有iv和密钥的AES 256位加密来加密字符串
SecureRandom random = new SecureRandom(); // quite heavy, look into a lighter method. String stringToEncrypt = "mypassword"; byte[] realiv = new byte[16]; random.nextBytes(realiv); Cipher ecipher = Cipher.getInstance("AES"); SecureRandom random = new SecureRandom(); // quite heavy, look into a lighter method. byte[] realiv = new byte[16]; random.nextBytes(realiv); byte[] secret = "somelongsecretkey".getBytes(); SecretKeySpec secretKey = new SecretKeySpec(secret, "AES"); ecipher.init(Cipher.ENCRYPT_MODE, secretKey, random); byte[] encryptedData = ecipher.doFinal();
但init()
只接受3个参数。 我需要一种方法来做类似的事情:
ecipher.init(Cipher.ENCRYPT_MODE, stringToEncrypt, secretKey, random);
通常,您不需要为具有确定性行为的算法生成随机数的东西。 此外,当您使用ECB块模式时,您不需要IV,这是Java默认的模式。 确切地说,Java默认为Cipher.getInstance("AES")
"AES/ECB/PKCS5Padding"
。
所以你应该可以使用这样的代码:
// lets use the actual key value instead of the platform specific character decoding byte[] secret = Hex.decodeHex("25d6c7fe35b9979a161f2136cd13b0ff".toCharArray()); // that's fine SecretKeySpec secretKey = new SecretKeySpec(secret, "AES"); // SecureRandom should either be slow or be implemented in hardware SecureRandom random = new SecureRandom(); // first create the cipher Cipher eCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // filled with 00h characters first, use Cipher instance so you can switch algorithms byte[] realIV = new byte[eCipher.getBlockSize()]; // actually fill with random random.nextBytes(realIV); // MISSING: create IvParameterSpec IvParameterSpec ivSpec = new IvParameterSpec(realIV); // create the cipher using the IV eCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); // NOTE: you should really not encrypt passwords for verification String stringToEncrypt = "mypassword"; // convert to bytes first, but don't use the platform encoding byte[] dataToEncrypt = stringToEncrypt.getBytes(Charset.forName("UTF-8")); // actually do the encryption using the data byte[] encryptedData = eCipher.doFinal(dataToEncrypt);
现在看起来好多了。 我已经使用Apache commons编解码器来解码hex字符串。
请注意,您需要使用encryptedData
保存realIV
,并且您没有包含完整性保护,例如MAC(对于密码,您可能不需要它)。
我强烈怀疑你想要做的是调用ecipher.doFinal(stringToEncrypt)
,如果你有更长的字符串,可能会在一系列doUpdate(...)
之后调用。
.init()
创建密码对象, update()
和doFinal()
填充加密输出并将明文作为输入。
当然,您需要在String
和字节数组之间进行转换 。