【问题标题】:RSA Key ( XML Format ) compatible for .Net与 .Net 兼容的 RSA 密钥(XML 格式)
【发布时间】:2012-09-20 12:21:10
【问题描述】:

如何生成应与 .NET 环境兼容的基于 xml 的 RSA 密钥(私有、公共)。我在 PHP 中尝试了 phpseclib 模块。但它与.NET 不兼容。请建议我用 Java 生成基于 xml 的 RSA 密钥的任何方法?实际上我正在研究基于 linux 的系统。使用这些密钥我将执行加密和解密操作。 喜欢

<RSAKeyValue>
    <Modulus>4hjg1ibWXHIlH...ssmlBfMAListzrgk=</Modulus>
    <Exponent>AQAB</Exponent>
    <P>8QZCtrmJcr9uW7VRex+diH...jLHV5StmuBs1+vZZAQ==</P>
    <Q>8CUvJTv...yeDszMWNCQ==</Q>
    <DP>elh2Nv...cygE3657AQ==</DP>
    <DQ>MBUh5XC...+PfiMfX0EQ==</DQ>
    <InverseQ>oxvsj4WCbQ....LyjggXg==</InverseQ>
    <D>KrhmqzAVasx...uxQ5VGZmZ6yOAE=</D>
</RSAKeyValue>

【问题讨论】:

  • 你的意思是说它们针对不同的 XSD 进行了验证?

标签: java .net encryption rsa


【解决方案1】:

Java 中没有开箱即用的支持,但它仍然相当简单。首先,您使用 JCA KeyPairGenerator 生成一个 RSA 密钥对。

然后,您需要将私钥转换为适当的接口(我们使用RSAPrivateCrtKey 而不是RSAPrivateKey,因此我们可以访问 CRT 部分),并使用 Apache Commons Codec 进行 Base64 编码。

public static void main(String[] args) throws Exception {
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    KeyPair keyPair = keyPairGen.genKeyPair();
    RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) keyPair.getPrivate();

    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", n);
    write(builder, "Exponent", e);
    write(builder, "P", p);
    write(builder, "Q", q);
    write(builder, "DP", dp);
    write(builder, "DQ", dq);
    write(builder, "InverseQ", inverseQ);
    write(builder, "D", d);
    builder.append("</RSAKeyValue>");

    System.out.println(builder.toString());
}

private static void write(StringBuilder builder, String tag, BigInteger bigInt) {
    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) {
    return new String(Base64.encodeInteger(bigInt), "ASCII");
}

如果您愿意,可以使用适当的 XML API,但在这种情况下,我认为没有什么令人信服的理由不使用 StringBuilder。此外,请随意内联 BigInteger 实例。我将它们声明为变量,以使 Java 方法和 XML 元素之间的映射更加明显。

【讨论】:

  • 您是否使用 Bouncy Castle 进行 Base64 编码?
  • 好的,已经投票了,但是导入声明不存在:)
  • 我确实在第二段中提到过;)
  • 臭小子,没看到。我会马上去配镜店,但这里是 23:25 :)
  • 谢谢..很有用。
【解决方案2】:

如果有人想做反向操作 - 通过 xml 文件获取 RSAPrivateCrtKey,不要忘记使用正号参数创建 BigInteger 实例。

new BigInteger(1, Base64.getDecoder().decode(encodedBigInteger));

避免潜在的异常

java.security.SignatureException: Could not sign data
    at sun.security.rsa.RSASignature.engineSign(RSASignature.java:178)
    at java.security.Signature$Delegate.engineSign(Signature.java:1207)
    at java.security.Signature.sign(Signature.java:579)
    ... more
Caused by: javax.crypto.BadPaddingException: Message is larger than modulus
    at sun.security.rsa.RSACore.parseMsg(RSACore.java:214)
    at sun.security.rsa.RSACore.crtCrypt(RSACore.java:166)
    at sun.security.rsa.RSACore.rsa(RSACore.java:122)
    at sun.security.rsa.RSASignature.engineSign(RSASignature.java:175)
    ... 6 more

【讨论】:

    猜你喜欢
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    相关资源
    最近更新 更多