1

everyone! When I try to convert a java.security.PrivateKey object to an org.bouncycastle.asn1.pkcs.RSAPrivateKey object, like the code show.

void prvKey2BCRSAPrvKey() throws Exception {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048);
    KeyPair keyPair = keyPairGenerator.genKeyPair();
    PrivateKey privateKey = keyPair.getPrivate();
    System.out.println(privateKey.getAlgorithm());
    RSAPrivateKey rsaPrivateKey = RSAPrivateKey.getInstance(privateKey.getEncoded());
    System.out.println(rsaPrivateKey.getVersion());
}

I always get an error.

java.lang.ClassCastException: org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integer

at org.bouncycastle.asn1.pkcs.RSAPrivateKey.(Unknown Source)

at org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(Unknown Source)

I know the problem is happening here.

RSAPrivateKey.getInstance(privateKey.getEncoded())

And more deep reason is in this function which is in org.bouncycastle.asn1.pkcs.RSAPrivateKey:

private RSAPrivateKey(ASN1Sequence var1) {
    Enumeration var2 = var1.getObjects();
    ASN1Integer var3 = (ASN1Integer)var2.nextElement();
    int var4 = var3.intValueExact();
    if (var4 >= 0 && var4 <= 1) {
        this.version = var3.getValue();
        this.modulus = ((ASN1Integer)var2.nextElement()).getValue();
        this.publicExponent = ((ASN1Integer)var2.nextElement()).getValue();
        this.privateExponent = ((ASN1Integer)var2.nextElement()).getValue();
        this.prime1 = ((ASN1Integer)var2.nextElement()).getValue();
        this.prime2 = ((ASN1Integer)var2.nextElement()).getValue();
        this.exponent1 = ((ASN1Integer)var2.nextElement()).getValue();
        this.exponent2 = ((ASN1Integer)var2.nextElement()).getValue();
        this.coefficient = ((ASN1Integer)var2.nextElement()).getValue();
        if (var2.hasMoreElements()) {
            this.otherPrimeInfos = (ASN1Sequence)var2.nextElement();
        }

    } else {
        throw new IllegalArgumentException("wrong version for RSA private key");
    }
}

When the code runs here, it goes wrong.

ASN1Integer var3 = (ASN1Integer)var2.nextElement();

But I don't know how to fix it. It is some code I write is wrong? I use java1.8 and the BC dependent libraries is

<dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.70</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.70</version>
    </dependency>

Someone can help me? Very very thanks!!!

Pai
  • 13
  • 3

1 Answers1

1

Java PrivateKey.getEncoded() returns the PKCS8 encoding of the key. This is in the javadoc for the superclass java.security.Key, admittedly not the most obvious place to look. With Bouncy, you can decode the PKCS8 using org.bouncycastle.asn1.pkcs.PrivateKeyInfo and extract the algorithm-specific part, which for RSA is the (PKCS1) RSAPrivateKey structure, and that is what you should feed to org.bouncycastle.asn1.pkcs1.RSAPrivateKey.getInstance -- you can use any of the ASN1Encodable returned from parsePrivateKey, the ASN1Sequence underlying it, or the byte[] returned by .getEncoded.

Compare How to convert a PKCS#8 encoded RSA key into PKCS#1 in Java? and maybe PEM encoding of ECDSA in Java (which is for ECC instead of RSA but the principle is the same; disclosure: my answer).

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • Thank you very much for your answer, I have solved the problem according to the idea you provided. – Pai Sep 22 '22 at 12:54