2012-12-24 55 views
4

我是RSA和密码学的新手,我需要使用RSA对数据进行加密和解密,我有一个java程序可以生成一个密钥对并将它们保存在一个.key文件中,格式为XML格式(它绝对可以,它通过加密和解密数据进行测试),然后我想在.NET应用程序中使用它们,我导入用于加密和解密的密钥。公钥是OK,没有问题加密得到完成,但私有密钥导入失败,出现以下异常消息RSA密钥对导入私钥的例外

Bad data (CryptographicException.ThrowCryptogaphicException(Int32 hr)) 

这是编码的公共密钥:

<RSAKeyValue> 
<Modulus>iFouk9viRs5dcvJCvDM1vXC4sBuSB9SPcdJhRyFLoNW/pka6MNAiu4cOksFRejiuM1ZswyJMy+ow 
lmLflJ/XrfnUQxLwLp61oij4CrzHKl9jjHorqIA7uEQKY8RBiUjZ7kbO5nFaIWs1NWMVks8Srdhv 
8pVd1sLKKUs66c/ndAk=</Modulus> 
<Exponent>AQAB</Exponent> 
</RSAKeyValue> 

,这是编码的公共密钥:

<RSAKeyValue> 
<Modulus>iFouk9viRs5dcvJCvDM1vXC4sBuSB9SPcdJhRyFLoNW/pka6MNAiu4cOksFRejiuM1ZswyJMy+ow 
lmLflJ/XrfnUQxLwLp61oij4CrzHKl9jjHorqIA7uEQKY8RBiUjZ7kbO5nFaIWs1NWMVks8Srdhv 
8pVd1sLKKUs66c/ndAk=</Modulus> 
<Exponent>AQAB</Exponent> 
<P>AO9WnDNOt9Xewnoy8KTed56Z+3Nfto6J8wCXKzX3LhuuiKNUBe8qFoinrteQJq/9NAEXnNCafxDW 
ThIkr9GtMxE=</P> 
<Q>AJHYMk0bOEGZlQbaJk3VDovvOJuRt5NI3WtXWl1v5VUW6aQQO3rV3+3GSN6Xa3hTKXtCVVL26Awy 
OkDykUPjQXk=</Q> 
<DP>KIHsJfLowlXVbIE6oWzVqg49tKU6bJ2Ed1Eeix+uuhisH5iU+ImTDsXynaFUKu0b5CNu8w9y+hKL 
XB7BcydxQQ==</DP> 
<DQ>di267NIersF1idzhZvY62FdbBmx4VaeYi+93sPkH2wA7CI+CsxF1Z6XhzETkd9bjaRaiLx0VgTR+ 
Eby8y0bt+Q==</DQ> 
<InverseQ>HYF8gahVyzsz0IotzKI2Oh53sJMZWVxsvzkhqGlDtY1THFGZE5j8kl/UK0+FSN6yOYxBIuKNZ7om 
MgLQEMK1PQ==</InverseQ> 
<D>DERQvGyjxsr6DUVOS7AvvYNOmklgseOlpA/RQJz2ONoCC+uBBLM07LoRzZImymAfC+9SiZukXRQM 
mvr6MlzPAm04NWyZNzbjhLvmn1gmvDclDZ9X9bhYp8MBftPWU5PFBALOjVpD+mlbI2lTYCugf6pJ 
MHEMe17mNJ0eWCerfAE=</D> 
</RSAKeyValue> 

请帮我理解正在发生的事情和私人密钥有什么问题。

这是解决问题的工作后确定的代码:

private String getPublicKeyXml(RSAPublicKey pk) throws UnsupportedEncodingException { 

    StringBuilder builder = new StringBuilder(); 
    builder.append("<RSAKeyValue>\n"); 

    byte[] m = pk.getModulus().toByteArray(); 
    byte[] mm = stripLeadingZeros(m); 

    write(builder, "Modulus", mm); 
    write(builder, "Exponent", pk.getPublicExponent()); 

    builder.append("</RSAKeyValue>"); 

    return builder.toString(); 
} 

private String getPrivateKeyXml(PrivateKey pk) throws UnsupportedEncodingException { 
    RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) pk; 
    BigInteger n = privKey.getModulus(); 
    BigInteger e = privKey.getPublicExponent(); 
    BigInteger d = privKey.getPrivateExponent(); 
    BigInteger p = privKey.getPrimeP(); 
    BigInteger q = privKey.getPrimeQ(); 
    BigInteger dp = privKey.getPrimeExponentP(); 
    BigInteger dq = privKey.getPrimeExponentQ(); 
    BigInteger inverseQ = privKey.getCrtCoefficient(); 

    StringBuilder builder = new StringBuilder(); 
    builder.append("<RSAKeyValue>\n"); 
    write(builder, "Modulus", stripLeadingZeros(n.toByteArray())); 
    write(builder, "Exponent", stripLeadingZeros(e.toByteArray())); 
    write(builder, "P", stripLeadingZeros(p.toByteArray())); 
    write(builder, "Q", stripLeadingZeros(q.toByteArray())); 
    write(builder, "DP", stripLeadingZeros(dp.toByteArray())); 
    write(builder, "DQ", stripLeadingZeros(dq.toByteArray())); 
    write(builder, "InverseQ", stripLeadingZeros(inverseQ.toByteArray())); 
    write(builder, "D", stripLeadingZeros(d.toByteArray())); 
    builder.append("</RSAKeyValue>"); 

    return builder.toString(); 
} 

private void write(StringBuilder builder, String tag, byte[] bigInt) throws UnsupportedEncodingException { 
    builder.append("\t<"); 
    builder.append(tag); 
    builder.append(">"); 
    builder.append(encode(bigInt).trim()); 
    builder.append("</"); 
    builder.append(tag); 
    builder.append(">\n"); 
} 

private void write(StringBuilder builder, String tag, BigInteger bigInt) throws UnsupportedEncodingException { 
    builder.append("\t<"); 
    builder.append(tag); 
    builder.append(">"); 
    builder.append(encode(bigInt)); 
    builder.append("</"); 
    builder.append(tag); 
    builder.append(">\n"); 
} 

private static String encode(BigInteger bigInt) throws UnsupportedEncodingException { 
    return new String(new sun.misc.BASE64Encoder().encode(bigInt.toByteArray())); 
} 

private static String encode(byte[] bigInt) throws UnsupportedEncodingException { 
    return new String(new sun.misc.BASE64Encoder().encode(bigInt)); 
} 

private byte[] stripLeadingZeros(byte[] a) { 
    int lastZero = -1; 
    for (int i = 0; i < a.length; i++) { 
     if (a[i] == 0) { 
      lastZero = i; 
     } else { 
      break; 
     } 
    } 
    lastZero++; 
    byte[] result = new byte[a.length - lastZero]; 
    System.arraycopy(a, lastZero, result, 0, result.length); 
    return result; 
} 
+0

我已经解决了这个问题em由我自己,在P,Q,Modulus或其他键的私钥中显示的数据在其字节数组的前导(起始)处不应该包含零,所以当我消除了它们可能的零时,问题就消失了。 – Areff

+2

请把它作为答案阿里夫发布。 Java确实会返回BigInteger值,如果你在BigInteger的实例上调用'toByteArray()',它将*返回带符号的表示。 *可能*包含第一个'00'h字节。由于模数始终具有密钥长度的大小并且具有最高位设置,所以'00'h总是被预置。请注意,其他值(包括私有指数)可能小于密钥大小,并且并非所有实现都接受更小的数组(在这方面不知道C#)。 –

+3

Areff,如果你下次发帖,请确保你在你的问题中包含代码,也许在你的答案中包含一些代码?过一段时间后你可以接受你自己的答案。 –

回答

0

公钥是OK和加密没有问题得到完成,但私有密钥导入失败,出现以下异常消息

坏数据(CryptographicException.ThrowCryptogaphicException(的Int32小时))

看看Cryptographic Interoperability: Keys“常见错误”部分下。仍然留在我的脑海中根深蒂固的那些:

  • 错误KeyNumber或密钥使用
  • 错误的加密服务提供商
  • 正确的加密服务提供程序,错误ProviderType
  • 加密服务提供程序不支持密钥大小
  • 在字节数组中取出0使得数组有一个太多的八位组