2014-06-20 142 views
0

我是Android开发人员。目前的任务是使用RSA算法通过提供给我的公钥模数和指数对我的Android应用程序中的数据进行加密,然后通过网络通过JSON字符串将其发送到.Net Web服务。该Web服务将解密数据并进一步使用它。在Android中加密数据和在WCF Web服务中解密数据时,要解密的数据超过128个字节的最大模数

,我用它来加密数据的代码如下:

public String RSAEncrypt (final String plain) throws Exception 
{ 
    try{ 
     String strModulus = "tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZ/HG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U="; 
     String strExponent = "AQAB"; 
     byte[] modulusBytes = strModulus.getBytes(); 
     byte[] exponentBytes = strExponent.getBytes(); 
     BigInteger modulus = new BigInteger(1, modulusBytes);    
     BigInteger exponent = new BigInteger(1, exponentBytes); 

     RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent); 
     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 = new String("Manchester United").getBytes("UTF-8"); 
     byte[] cipherData = cipher.doFinal(plainBytes); 
     encryptedString = Base64.encodeToString(cipherData, Base64.NO_PADDING); 
    } 
    catch(Exception e){ 
     Log.e("Error", e.toString()); 
    } 

    return encryptedString; 
} 

上面的代码给了我,我传递给.NET Web服务的字符串。但由于某种原因,Web服务无法正确解密这些数据,并出现错误: 要解密的数据超过128个字节的最大模数

我试图帮忙,但我无法理解什么正在发生。

我在我的代码中做了如下修改: Cipher cipher = Cipher.getInstance(“RSA/ECB/PKCS1Padding”);而不是 密码cipher = Cipher.getInstance(“RSA”);

在加密数据时还提供了'Base64.NO_PADDING'。

的ASP.Net代码如下:

  const int PROVIDER_RSA_FULL = 1; 
      const string CONTAINER_NAME = "Tracker"; 

      CspParameters cspParams; 
      cspParams = new CspParameters(PROVIDER_RSA_FULL); 
      cspParams.KeyContainerName = CONTAINER_NAME; 
      RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(cspParams); 
      rsa1.FromXmlString("<RSAKeyValue><Modulus>tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZ/HG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U=</Modulus><Exponent>AQAB</Exponent><P>6e0nv7EBFBugtpoB+ozpg1J4js8E+DVyWCuBsERBPzqu4H7Z/oeLIRSC8Gi5GZgrCpBf3EvyIluM7rzaIfNThQ==</P><Q>x/29X9ns1WcXC42IJjLDjscz5ygdVh79dm8B2tQVbqwyhDsQ6OIOQdu5+eHf4hUMoTrM9KkS2F6FGlLXuaOFoQ==</Q><DP>kTS2LMaJ/dpce5zDx6w6s1q5HSSiWBSNIu/2s9zah448yXvUg6vNkD40PVk0NRAA/7C44H2AExWzOOqfmN17JQ==</DP><DQ>xtAx9drQPWnpl/uQUOEAVa0kpPTVDStrr9Q1FNTnpYkcAyYw7kLkB4anAIoSpk9kqdeprsNxz5VPXtbiTFMKYQ==</DQ><InverseQ>O0594NMjnjSp+/NAa1kQxoQNzn1qqq+p1Zb+kT3/jRc/0d7ZnqSSpxFMXfxx3yZkNAOPDOdbckPQbRZ13RKBHg==</InverseQ><D>bjVEagwvkrZaTt9CTW1hd3362weLFlX6DpE/3R3RcrpVfkSwKGpEhqGrNeeGPlsuqiaf5rAFir4eTqrF1QVliKsU4XE0RyzP5lHGc7dlX4DOHMjs2R9nNWv8QOTPoaRuLrLGorqBXlw/jQPxFI6gQzkIIjzuf//lDVnFam3dw4E=</D></RSAKeyValue>"); 

      string data2Decrypt = "SeuUUjdSbFQlcwaCFVZ9fN0t3aXpItXU4+pkuztVgky77SBokBATKj+56+irtCfT1lSGRZbbzgQTd8zpcjPsT6J+7AyBwRwuv418JyKINNxPsDVFKfupViu8MOoxWzjmjZE5p54AjByA6dzGSR9UogFHhFSMZWJ5OELwZFSz5wFHyMaeIm1UnEiRDDjPTY/aIuh56WnZPXUmP3D54bAwDXPFtY0JjjiyxZetnA"; 

      byte[] encyrptedBytes = Convert.FromBase64String(data2Decrypt); 

      byte[] plain = rsa1.Decrypt(encyrptedBytes, false); 
      string decryptedString = System.Text.Encoding.UTF8.GetString(plain); 

发生该错误的位置: 字节[]平原= rsa1.Decrypt(encyrptedBytes,FALSE);

Decrypt是.Net本身的RSACryptoProvider类的一个函数。

我已经检查像几个环节: The data to be decrypted exceeds the maximum for this modulus of 128 bytes. RSA DECRYPTION c#

The data to be decrypted exceeds the maximum for this modulus of 128 bytes

不过,我不能够实现的建议。任何帮助将不胜感激。谢谢!

回答

0

在Java代码,必须编码为的Base64串的模数和指数,但通过使用字符串编码解码转换那些字节阵列(例如UTF-8),让你伪字节值。这是给你比您预期完全不同的RSA密钥:

孙RSA公共密钥,1375位 模量:750169282846494125860884712723073313436806987678989257696854519163422196468501094334772708285571263987960096312310946772203386096382092764988823316042225715695209682181694351362408270131738979229545667503402617569939108631330090897309670319383704572983438399762295114985980168234669536869729771611691862551491497864929321166916789165923322527018195770714618713254889722551163557798154618552019060264304749542004029 公用指数:1095844162

你的密文是在模数1375,而不是1024,所以错误字符串是正确的。 Java产生的模数1375(172字节)的密文超过.NET代码的模数,该代码仍然是1024(限于128字节。)

相反,如果你的Base64解码这样的字符串,例如:

byte[] modulusBytes = DatatypeConverter.parseBase64Binary("tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZ/HG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U="); 
byte[] exponentBytes = DatatypeConverter.parseBase64Binary("AQAB"); 

那么你会得到你想要的关键:

孙RSA公共密钥,1024位 模:128329253200625851747417306407495181460638722403079978934516135424027698446198581565013203888628021918042144433585511434660221274570695228957705446643239452347022609986771847076542293947545868471690675464836702700925020694185362910844461481736938124375366838112503820421836105957170854998527632432367452987301 公共exponen T:65537

和Java代码将产品这样的结果:

“P2ENQbBu3rpBcrfnzbOj6MLCGBABclQnVY6QpHJ54uXZnKSd2Ll9fJ6g + avsvbWib9SNKsL9Yx + PeRdC20W6BXfblSnXMAbZxJ2VQCQho44rR + k6B9HrB2i0zl9pdLSRxm9k0poQVG1I/yplmK1H9TGqlZp1oYnbzWrS8JiRd5w =”

和您的.NET代码会被正确解密,以 “曼联”。

编辑:

Base64.decode应该匹配DatatypeConverter.parseBase64Binary的输出。输出我用这个循环得到:

for (int i = 0; i < modulusBytes.length; i++) 
{ 
    System.out.print(" "); 
    System.out.print(modulusBytes[i]); 
} 
System.out.println(); 

是这样的:

-74 -65 54 81 -9 -122 122 -43 123 -56 18 -100 56 -8 -59 77 107 59 -92 122 -86 -81 -2 88 40 -91 -116 81 -97 -57 27 -127 -25 10 101 -85 102 -61 -95 -71 29 69 6 115 25 -2 13 -104 -118 -117 40 74 91 -76 -51 -34 -44 -109 63 101 95 -68 47 -39 18 -33 89 119 -52 -67 -106 6 -92 0 47 125 -123 -80 -51 -68 -112 -38 45 106 -6 -46 -124 -2 -40 96 40 -37 28 -95 36 94 -106 80 -61 -6 -30 92 98 125 71 -30 25 -38 -71 -43 114 96 -111 -3 -102 37 97 56 -88 74 -108 76 76 -49 15 26 -97 -91 

尝试在.NET平台上的串Base64编码解码,看看它在Java平台上的解码结果相匹配。

+0

这是一个真正的好方案。这应该适用于我。唯一的问题是,Android不让我使用'DatatypeConverter.parseBase64Binary',我不得不使用'Base64.decode()',它不提供所需的输出。我试图导入'javax.xml.bind.DatatypeConverter'的包,但无法正确实现。我很抱歉,但还有什么可以满足我的需求吗? – Bot

+0

两个Base64解码器都应该产生相同的输出,所以问题出在Base64.decode上,而不是加密上。看到我上面的编辑。 –

+0

此代码在Java中完美工作。但在Android中不太好。在WCF中,当我解密使用Java代码加密的字符串时,我得到了正确的值,但是我得到了Android的错误。问题是'byte [] cipherData'对于Java和Android来说是不一样的。我似乎无法理解为什么。 – Bot