我正在使用Java加密文本,并尝试在Linux上使用Openssl对其解密。我正在CBC上使用AES-128。
当我使用Openssl解密Java生成的64个字符加密的字符串时,我收到来自Openssl的“错误解密”错误。但是,如果字符串是16个字符,则Openssl可以正确解密它。
我正在Linux上运行它:
echo ${encryptedText} | ./openssl aes-128-cbc -d -a -K $( echo -n ${KEY} | hexdump -v -e '/1 "%02X"') -iv $(echo -n ${IV} | hexdump -v -e '/1 "%02X"')
注意:$ encryptedText,$ KEY,$ IV作为字符串而不是十六进制传递。此命令将其转换为十六进制: $(echo -n $ {KEY} | hexdump -v -e'/ 1“%02X”')
并收到此错误:
358048944:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:evp_enc.c:460:
我来自Java的加密代码基本上是:
import javax.crypto.*;
Cipher cipher;
SecretKey key;
String IV;
IvParameterSpec params;
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String randomString = GENERATE_RANDOM_TYPEABLE_ASCII(16_LENGTH);
key = new SecretKeySpec(randomString.getBytes("UTF-8"), "AES");
IV = GENERATE_RANDOM_TYPEABLE_ASCII(16_LENGTH);
params = new IvParameterSpec(IV.getBytes("UTF-8"));
cipher.init(Cipher.ENCRYPT_MODE, key, params);
byte[] encryptedTextBytes = cipher.doFinal((decryptedString).getBytes("UTF-8")); // decryptedString is passed as a parameter
String encryptedText = new Base64().encodeAsString(encryptedTextBytes);
return encryptedText;
我不明白的是为什么我的密码只能用于16个字符串,但不能用于64个字符串。
要注意的另一件重要事情是,如果我使用http://aes.online-domain-tools.com/之类的在线工具解密文本,则字符串可以完美解密。因此,我认为我的加密工作正常,但由于某种原因,OpenSSL出现了问题。
答案 0 :(得分:1)
我没有重现您的问题,但怀疑这是导致您遇到问题的原因:Base64.encodeAsString()
函数在使用时会返回一个长字符串,而不是16个字符宽的块:
import org.apache.commons.codec.binary.Base64;
public class B64Test {
public static void main(String[] args) {
byte[] plaintext = new byte[100];
String b64text = new Base64().encodeAsString(plaintext);
System.out.println(b64text);
}
}
提供输出
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
如果要将其馈送到openssl
中进行解码,则需要提供附加选项-A
以使openssl
base64在一行上处理数据。请注意,-A
需要与-a
或-base64
一起使用,这是同一件事,但可读性更高。 openssl enc的文档对此进行了说明。
或者,您可以告诉Base64()
构造函数在例如64个字符之后插入换行符,如下所示:
String b64text = new Base64(64).encodeAsString(plaintext);