使用.NET进行公钥加密,使用Java进行解密

本文关键字:使用 解密 Java 公钥加密 NET | 更新日期: 2023-09-27 18:27:28

我有一个要求,Java Web服务公开客户端获取PublickKey(作为PEM字符串)的方法,并向使用PublicKey加密的Web服务提交数据。该服务的客户端是.NET应用程序。在Java端,使用密钥对(RSA 1024位)创建密钥库,如下所示keytool.exe-genkey-alias abc-keystore sample.ks-storetype jceks-storepass xyz

.NET客户端通过web服务获得PublicKey,然后使用该公钥加密一些敏感数据,以使用加密的数据调用web服务。web服务使用密钥库中可用的私钥解密数据,并将内容存储在DB中。由于客户端兼容性的原因,我无法使用任何WS-Security功能。

Web服务读取密钥库,并将公钥作为PEM字符串返回。.NET客户端获取作为PEM字符串的PublicKey,并使用它创建RSACryptoServiceProvider,它可以毫无问题地工作。然后它解密数据并将其提交回Java Web服务。

Java服务解密数据,但我遇到的问题是它打印出垃圾(而不是ASCII数据)。我没有得到任何异常

我在这里附上了代码的片段(简化)

.NET客户端

  var registrationService = new RegistrationService();
  var pKey = registrationService.getPublickey();
  //pKey is a PEM String
  X509Certificate2 cert = new X509Certificate2(ASCIIEncoding.ASCII.GetBytes(pKey));
    RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PublicKey.Key;
    var encryptedMsg = rsa.Encrypt(Encoding.UTF8.GetBytes("Secret Data"), false);
    var encoded_msg = Convert.ToBase64String(encryptedMsg);
    registrationService.submitRegistration(encoded_msg);

Java端:

   public void submitRegistration(String inputData)
   {
   //Decoding the encoded and encrypted message in the webservice      
   PrivateKey privateKey = getPrivateKeyFromKeyStore("abc");
   //I know I am using JDK proprietary classes, but I can easily replace this
   byte[] dataInBytes = new Base64Decoder().deodeBuffer(inputData)
   Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); 
   cipher.init(Cipher.DECRYPT_MODE, privateKey);
   byte[] decryptedData = cipher.doFinal(dataInBytes);          
   String original = new String(decryptedData, "UTF-8");
   System.out.println("Original Data : " + original);
}
  public String getPublicKey()
  {
    Certificate cert = getKeyStore().getCertificate("abc");
    byte[] encodedCert = cert.getEncoded();
    StringWriter sw = new StringWriter();
    sw.write("-----BEGIN PUBLIC KEY-----");
    sw.write(new Base64Encoder().encode(encodedCert));
    sw.write("-----END PUBLIC KEY-----");
    return sw.toString();
  }

使用.NET进行公钥加密,使用Java进行解密

需要注意的一点是,您在Java端使用"NOPADDING",但.NET使用的是PKCS1Padding。

由于PKCS1填充在高位端用0x00 0x02填充明文,这也为解密端提供了一种检查其是否使用正确私钥的方法。但是,请注意,错误的密钥解密为以0x00 0x02开头的明文的几率至少为1/65536,因此不能完全依靠此检查来检测不正确的私钥。在您的情况下,您使用了不正确的密钥,并且明文未通过此检查,因此您收到了异常。现在,当您指定NOPADDING时,您表示所有明文都是有效的,任何进一步的检查都将由您的应用程序完成。