Java Cipher AES不加密整个字符串

问题描述

我正在尝试使用带有AES算法的java Cipher加密和解密字符串。但是不知何故它不想加密整个字符串。我的目标不是安全地加密某些微粒,而是希望某人不能很容易地读取String(后来存储在文件中)。

要加密,我使用以下代码

''.join(result) # EFCDAB

为了解密,我使用以下代码

Cipher cipher = Cipher.getInstance("AES");
byte[] input = plain.getBytes();
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[] encrypted = cipher.doFinal(input);

return new String(encrypted);

要测试上述代码,我使用以下参数:

Cipher cipher = Cipher.getInstance("AES");
byte[] input = encrypted.getBytes();
cipher.init(Cipher.DECRYPT_MODE,key);
byte[] decrypted = cipher.doFinal(input);

return new String(decrypted);

该测试产生的是加密后再解密的字符串:

SecretKeySpec key = new SecretKeySpec(new byte[]{103,38,125,-67,-71,-23,-119,102,78,-3,-33,-5,32,-112,-124},"AES");
String plain = "Lorem ipsum dolor sit amet,consectetur adipiscing elit. Curabitur auctor ornare bibendum."

解决方法

有几个问题:

byte[] encrypted = cipher.doFinal(input);
return new String(encrypted);

问题是您不能仅仅“字符串化”字节数组,而是需要以其他格式(例如Base64或Hex)表示字节数组。 String 仅用于可打印字符。

Problems converting byte array to string and back to byte array

byte[] encrypted = cipher.doFinal(input);
return Base64.getEncoder().encodeToString(encrypted);

以同样的方式-解密之前,您需要将编码后的字符串解码为字节数组。

编辑:

另一个问题-您应指定完整的mode of operation

默认情况下,如果提供了IV(初始化矢量),则“ AES”参数应使用CBC模式,而如果未定义IV,则应使用ECB模式(就我所知,这至少是Oracle JDK的工作方式)。

并非所有运行时都保证。您正在使用哪个平台/ jre? 。当您对第一个字节块进行加密时,我假设实现使用的是随机IV(可以使用cipher.getIV()),并且解密时必须通过IV。

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
SecretKey symmetricKey = new 
SecretKeySpec(encryptionParams.getKey(),SYMMETRIC_KEY_ALG);

cipher.init(Cipher.ENCRYPT_MODE,symmetricKey,ivParamSpec);

对于CBC,IV必须是长度为AES块大小(128位= 16字节)的随机字节数组,通常的做法是将IV放在密文前面。

请确实学习有关正确使用加密的知识,否则您可能会得到不安全的解决方案。

我有一个小的reference project,您可以尝试使用。