微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法在服务器上解密 RSA 加密内容由客户端

如何解决无法在服务器上解密 RSA 加密内容由客户端

我们有一个客户端服务器系统,其中客户端(Android 手机)和服务器(spring)都使用 java.security.KeyFactory 来获取 java.security.KeyFactory 的实例,如下所示:

KeyFactory factory = KeyFactory.getInstance("RSA");

但是如果我们这样做,当我们使用这个工厂来加密数据时,服务器给出不同的输出,客户端给出不同的输出。当我们检查提供程序时,服务器使用的是 SunRsaSign,客户端使用的是 OpenSSlrsA。所以我们尝试使用以下方法在客户端上设置相同的内容

KeyFactory factory = KeyFactory.getInstance("RSA","SunRsaSign");

但是我们得到 java.security.NoSuchProviderException 错误。同样,当我们尝试在服务器上设置 OpenSSlrsA 时,它们也面临同样的错误

服务器和客户端加密的完整代码如下:

String pubKey = "<key here>"
byte[] keyData = DatatypeConverter.parseHexBinary(pubKey);
System.out.println("key data" + Arrays.toString(keyData));
KeyFactory factory = KeyFactory.getInstance("RSA");
//System.out.println("provide = " + factory.getProvider());
PublicKey pub = factory.generatePublic(new X509EncodedKeySpec(keyData));
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE,pub);
byte[] secretMessageBytes = msg.getBytes(StandardCharsets.UTF_8);
System.out.println("secret msg" +Arrays.toString(secretMessageBytes));
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
System.out.println("enc data" +Arrays.toString(encryptedMessageBytes));

encryptedMessageBytes 生成的不同。这可能是个问题吗?我认为这是因为不同的平台使用了不同的 Provider。

有人可以帮助我如何设置 KeyFactory 的提供程序或如何删除解密错误 (javax.crypto.BadPaddingException)?

解决方法

发布的代码,在 Android 和 Java/Spring 端都使用,在实例化密码时只指定算法而不是填充:

Cipher.getInstance("RSA")

在没有明确指定填充的情况下,使用双方提供者的默认填充。但是,不同的提供者通常定义不同的默认填充(例如 NoPaddingPKCS1PaddingOAEPPadding)。不同的填充会导致解密失败,因为成功解密的前提是使用与加密相同的填充。

为避免此类情况,在实例化密码时应始终指定填充,尤其是在跨平台环境中,例如:

Cipher.getInstance("RSA/ECB/PKCS1Padding")

左边是算法,右边是填充。注意中间部分(ECB)对RSA没有意义(它是使用对称加密方案的产物,中间指定了操作模式,非对称加密没有定义)。

通过显式指定填充来解决问题证明填充确实是问题所在。


我只能推测您的环境中使用的默认填充。

我无法测试 OpenSSLRSA 提供程序,因为它在我的环境中不可用。在我的机器上,Android(API 级别 28,P)应用了 AndroidOpenSSL 提供程序(又名 Conscrypt)。这默认为 NoPadding,而 Java 的 SunJCE 提供程序默认为 PKCS1Padding。 Android 上的加密和 Java 上的解密会导致异常(或另一个方向的未删除填充)。

您可以按如下方式确定您的环境的默认填充:使用默认填充(通过仅指定算法)加密并在解密时改变填充直到解密成功并且原始明文被解密。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?