java Android:使用 iv 和密钥使用 AES 256 位加密加密字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13205019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:52:21  来源:igfitidea点击:

Android: Encrypt a string with AES 256bit Encryption with iv and secret key

javaandroidencryptionaes

提问by KJW

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();

but the init()only takes in 3 parameters. I need a way to do something like:

init()只接受 3 个参数。我需要一种方法来做类似的事情:

ecipher.init(Cipher.ENCRYPT_MODE, stringToEncrypt, secretKey, random);

回答by Maarten Bodewes

In general you don't need something that generates random numbers for an algorithm that has deterministic behavior. Furthermore, you don't need an IV when you are using ECB block mode, which is what Java defaults to. To be precise, Java defaults to "AES/ECB/PKCS5Padding"for in Cipher.getInstance("AES").

通常,您不需要为具有确定性行为的算法生成随机数的东西。此外,当您使用 ECB 块模式时,您不需要 IV,这是 Java 默认的。准确地说,Java 默认为"AES/ECB/PKCS5Padding"for in Cipher.getInstance("AES")

So you should be OK with code like this:

所以你应该可以使用这样的代码:

// 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);

Now that looks a whole lot better. I've used the Apache commons codec for decoding the hexadecimal string.

现在看起来好多了。我使用 Apache 公共编解码器来解码十六进制字符串。

Note that you need to save the realIVwith the encryptedData, and that you haven't included integrity protection, e.g. a MAC (for passwords, you may not need that though).

请注意,您需要保存realIVencryptedData和你有没有包括完整性保护,如MAC(口令,你可能不需要,虽然)。

回答by Jeff Ferland

I strongly suspect that what you want to do is call ecipher.doFinal(stringToEncrypt), possibly after a series of doUpdate(...)if you have longer strings.

我强烈怀疑您想要做的是调用ecipher.doFinal(stringToEncrypt)doUpdate(...)如果您有更长的字符串,可能会在一系列之后调用。

.init()creates the cipher object, update()and doFinal()populate the encrypted output and take the plaintext as input.

.init()创建密码对象,update()doFinal()填充加密输出并将明文作为输入。

Of course, you'll need to convert between Stringand a byte array.

当然,您需要String和 字节数组之间进行转换