简体   繁体   English

Java AES加密问题

[英]Java AES encryption issue

Every time the encryption values changed by using AES, let anyone investigate the below code and let me know the issue 每次使用AES更改加密值时,请让任何人调查以下代码并让我知道该问题

code: 码:

private static final String secretKeys = "58BA833E57A51CBF9BF8BAB696BF9"

public static String encrypt() throws Exception {
        byte[] salt = new byte[16];
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        PBEKeySpec pbeKeySpec = new PBEKeySpec(secretKeys.getChars(),salt,1000, 256);
        Key secretKey = factory.generateSecret(pbeKeySpec);
        byte[] key = new byte[32];
        byte[] iv = new byte[16];
        SecretKeySpec secret = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] result = cipher.doFinal("welcome".getBytes("UTF-8"));
        String s = Base64.getEncoder().encodeToString(result);
        return s
        }

Output first time I got the below-encrypted string 输出第一次我得到以下加密的字符串

CZRIP35M4CnJtuDQ6YpmaQ==

The second time I got the below-encrypted string 我第二次得到以下加密的字符串

/fylTjohAZDsnCaHhiZo3A==

I have three questions: 我有三个问题:

  1. why the encrypted string not a constant? 为什么加密的字符串不是常量?

  2. how can I set the Blocksize? 如何设置Blocksize? ( AES.BlockSize = 128; ) AES.BlockSize = 128;

  3. How can I set the padding mode? 如何设置填充模式? ( AES.Padding = PaddingMode.PKCS7; ) AES.Padding = PaddingMode.PKCS7;

  1. For the first question, @Freiheit already answered this . 对于第一个问题,@ Freiheit已经回答了这个问题 Long story short, based on the iv (initilization vector) which acts as a salt and will be different for each encryption. 长话短说,基于iv(启动向量),它充当盐,并且对于每个加密将是不同的。 Having that said, encrypting the same plain text will result in different encrypted text, but the decryption (if necessary) will result back into the same plain text. 话虽如此,加密相同的纯文本将导致不同的加密文本,但解密(如果需要)将返回到相同的纯文本。 IV is helpful to make the encryption predictable. IV有助于使加密可预测。 Having stored the same password for 2 different users in a database will have different values, but will be the same password. 在数据库中为2个不同的用户存储相同的密码将具有不同的值,但密码相同。

  2. With the current cipher configured, you already have 128 block size. 配置当前密码后,您已经拥有128个块大小。 You can read more about the different cypher transformation here . 您可以在此处阅读有关不同cypher转换的更多信息。 You can also find more information of the block sizes for different algorithms here 您还可以在此处找到有关不同算法的块大小的更多信息

  3. You just need to change the Cipher.getInstance() to AES/CBC/PKCS7Padding 您只需将Cipher.getInstance()更改为AES/CBC/PKCS7Padding

1) the encrypted text is always different because the Cipher initialization is providing it's own IV since you are not providing one. 1)加密文本总是不同的,因为Cipher初始化提供它自己的IV,因为你没有提供。 You need to provide the IV you've "computed" in order to have a consistent output. 您需要提供已经“计算”的IV才能获得一致的输出。 Remember you never want to use an IV more than once for whatever this code is ultimately intended to do. 请记住,对于此代码最终打算执行的操作,您绝不会多次使用IV。

2) The keysize can be 128, 192 or 256 but the blocksize is always 128. 2)密钥大小可以是128,192或256,但块大小总是128。

3) Java only provides PKCS5, but there is no difference in the implementation for AES. 3)Java仅提供PKCS5,但AES的实现没有区别。 see what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding 看看pkcs5-padding-and-pkcs7-padding之间有什么区别

As was already pointed out there are several problems with the code provided such as the first lines not actually doing anything and the key and iv both being uninitialized. 正如已经指出的那样,提供的代码存在一些问题,例如第一行没有实际执行任何操作,而键和iv都未初始化。 I would additionally suggest you use SecureRandom to initialize your key and iv. 我还建议您使用SecureRandom初始化您的密钥和iv。 If you plan on using only a single AES key, this can be computed once and placed in the code or configuration file instead of running PBKDF2 every time. 如果您计划仅使用一个AES密钥,则可以计算一次并将其放在代码或配置文件中,而不是每次都运行PBKDF2。

Only adding to the answer provided by @micker, you need to invoke another version of Cipher.init() ; 只添加@micker提供的答案,您需要调用另一个版本的Cipher.init() ; one that takes the IV into account: 将IV考虑在内的:

...
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv); // <= Wrap your IV bytes here.
SecretKeySpec secret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec); // <= Add IV here.
...

That being said, the implementation suffers from a slew of other issues (key being all zeroes, IV being all zeroes, first 4 line don't do anything for you (as @JBNizet pointed out)). 话虽这么说,实现还有很多其他问题(关键是全零,IV全为零,前4行不为你做任何事情(正如@JBNizet指出的那样))。 I hope you are only using it to study how Java's encryption mechanics works. 我希望你只是用它来研究Java的加密机制是如何工作的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM