2

在 Java 中使用 RSA 加密/解密时,我面临一个非常特殊的问题。

示例代码:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();

Cipher enc = Cipher.getInstance("RSA");
enc.init(Cipher.ENCRYPT_MODE, kp.getPublic());
String CipherText = new String(enc.doFinal(PlainText.getBytes()));
System.out.println("CipherText: ") + CipherText);

Cipher dec = Cipher.getInstance("RSA");
dec.init(Cipher.DECRYPT_MODE, kp.getPrivate());
PlainText = new String(dec.doFinal(CipherText.getBytes()));
System.out.println("PlainText: " + PlainText);

每个人都可以清楚地看到:我使用公钥加密明文,然后使用私钥解密密文。

此代码崩溃并显示以下消息:

Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero

我还尝试明确使用“RSA/ECB/NoPadding”,但在解码期间失败。(例如,解码后的密文与原始明文不匹配)。

最后但并非最不重要的一点是,我尝试在使用我自己的 PKCS1.5 填充函数(也就是 PKCS1.5 规范)时执行此操作:

EMB = 00 || 02 || 研发 || 00 || MD
EMB 是长度为 k 的编码消息块,
其中 RD 是 8 个随机非零字节
MD 是最大长度 k = 11,并且可选地用零字节填充以使 EMB 长度为 k。

经过两天的测试,我只能得出结论,Java 中的 RSA 算法存在缺陷,或者根本没有执行我期望它执行的操作。

非常欢迎对上述代码提出任何建议或修复,因为我完全不明白为什么上述代码不能按预期工作。

4

1 回答 1

2

不要这样做:

String CipherText = new String(enc.doFinal(PlainText.getBytes()));

两个原因:

  • 在不指定编码的情况下调用几乎不是一个好主意。String.getBytes()您真的希望结果依赖于系统默认编码吗?
  • 将二进制加密操作的结果(即不透明的二进制数据)视为编码字符串绝对不是一个好主意。将其编码为 Base64 或十六进制。

您可以使用Apache Commons Codec来执行 base64 编码/解码操作,或者这个独立的公共域编码器/解码器

于 2011-05-27T09:16:41.343 回答