sat
sat

Reputation: 14949

RSA Key ( XML Format ) compatible for .Net

How to generate xml based RSA keys ( private ,public ) which should be compatible for .NET environment. I tried phpseclib module in PHP. But it is not compatible for .NET. Please suggest me any way to generate the xml based RSA keys in Java ? Actually I am working on linux based system. Using these keys I am going to perform encryption and decryption operation. Like

<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>

Upvotes: 4

Views: 12044

Answers (2)

Vsevolod Kaimashnikov
Vsevolod Kaimashnikov

Reputation: 23

If someone wants do reverse operation - take RSAPrivateCrtKey by xml file, do not forget create instance of BigInteger with positive signum parameter.

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

It avoids of potential exception

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

Upvotes: 0

David Grant
David Grant

Reputation: 14225

There's no support for this out of the box in Java, but it's still fairly trivial. First off, you generate an RSA key pair using the JCA KeyPairGenerator.

Then, you need to cast the private key to the appropriate interface (we use RSAPrivateCrtKey instead of RSAPrivateKey so we can access the CRT parts), and using Apache Commons Codec for Base64 encoding.

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");
}

You can use a proper XML API if you're so inclined, but I felt no compelling reason not to use StringBuilder in this case. Also, feel free to inline the BigInteger instances. I declared them as variables to make the mapping between Java methods and XML elements more obvious.

Upvotes: 7

Related Questions