将C#RSACryptoServiceProvider转换为JAVA代码

我得到了由Web服务团队编写的这个C#代码,它公开了我计划使用的一些Web服务。 我的密码需要使用此代码加密,以便Web服务知道如何在其末端解密它。

using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(publicKey); byte[] plainBytes = Encoding.Unicode.GetBytes(clearText); byte[] encryptedBytes = rsa.Encrypt(plainBytes, false); return Convert.ToBase64String(encryptedBytes); } 

我正在使用Java来使用这个Web服务,而且现在,我在将#C代码转换为Java代码时遇到了问题,因为该Web服务无法正确解密我的密码。

这是我目前失败的尝试: –

 // my clear text password String clearTextPassword = "XXXXX"; // these values are provided by the web service team String modulusString = "..."; String publicExponentString = "..."; BigInteger modulus = new BigInteger(1, Base64.decodeBase64(modulusString.getBytes("UTF-8"))); BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(publicExponentString.getBytes("UTF-8"))); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); String encodedEncryptedPassword = new String(Base64.encodeBase64(cipher.doFinal(clearTextPassword.getBytes("UTF-8")))); 

我做错了什么? 非常感谢。

2013-08-07 – 更新

我正在阅读这个网站 ,我意识到我的模数值和公共指数值不是hex。 所以,我修改了我的代码并尝试使用RSA/ECB/PKCS1PADDING提到的RSA/ECB/PKCS1PADDING PKCS1PADDING。

 // my clear text password String clearTextPassword = "XXXXX"; // these are the actual values I get from the web service team String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc="; String publicExponentString = "AQAB"; Base64 base64Encoder = new Base64(); String modulusHex = new String(Hex.encodeHex(modulusString.getBytes("UTF-8"))); String publicExponentHex = new String(Hex.encodeHex(publicExponentString.getBytes("UTF-8"))); BigInteger modulus = new BigInteger(modulusHex, 16); BigInteger publicExponent = new BigInteger(publicExponentHex); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); String encodedEncryptedPassword = new String(base64Encoder.encode(cipher.doFinal(clearTextPassword.getBytes("UTF-8")))); 

当我点击web服务时,我收到了这个错误: “要解密的数据超过了这个128字节模数的最大值。” 似乎明文密码仍未正确加密。

非常感谢任何帮助或建议。 谢谢。

2013-08-09 – 解决方案

我在下面发布了最终的工作解决方案

找到了解决方案。

 String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc="; String publicExponentString = "AQAB"; byte[] modulusBytes = Base64.decodeBase64(modulusString); byte[] exponentBytes = Base64.decodeBase64(publicExponentString); BigInteger modulus = new BigInteger(1, modulusBytes); BigInteger publicExponent = new BigInteger(1, exponentBytes); RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, publicExponent); KeyFactory fact = KeyFactory.getInstance("RSA"); PublicKey pubKey = fact.generatePublic(rsaPubKey); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] plainBytes = clearTextPassword.getBytes("UTF-16LE"); byte[] cipherData = cipher.doFinal(plainBytes); String encryptedStringBase64 = Base64.encodeBase64String(cipherData); 

根据RSACryptoServiceProvider.Encrypt上的MSDN文档,当第二个参数为false ,密码使用PKCS#1 v1.5填充。 所以你的密码规范是不正确的。

请尝试使用RSA/ECB/PKCS1PADDING

您正在将您的密钥材料转换为第二个代码示例,并且您已将其损坏,最终使您的密码认为您拥有的密钥材料比您实际拥有的密钥材料更长,并且使您的消息过长(这会触发您的错误)以及无法理解到另一端的解密密码。 直接转换为字节数组并将其传递给BigInteger

 String modulusString = "..."; String publicExponentString = "..."; byte[] mod = Base64.decodeBase64(modulusString); byte[] e = Base64.decodeBase64(publicExponentString); BigInteger modulus = new BigInteger(1, mod); BigInteger publicExponent = new BigInteger(1, e);