How to get a RSA PublicKey by giving a PrivateKey?
Asked Answered
F

6

12

I am looking for a Java function that will get an RSA PrivateKey and will return the correct RSA PublicKey?

Alternatively, is there a function that will tell us if the RSA PrivateKey/PublicKey is valid?

Francinafrancine answered 5/7, 2012 at 13:28 Comment(3)
Keep cool. A forum is quite differend from a live chat. Keep always in mind the users are here with their own free will and whenever they want and can.Iguana
Define what you mean by "valid".Plattdeutsch
Besides the answers given, if you can always perform a sign/verify (on any value) to see if the keys match. Note that once in a while this is troublesome, e.g. if a use count is kept for a private key (some HSM's and smart cards do). Comparing just the modulus or a hash over the modulus is fine too, the modulus should be unique for each key pair. No need for the public exponent.Rosenthal
Z
13

If you have your private key as an RSAPrivateCrtKey object, you can get the public exponent as well as modulous.

Then you could create the public key like so:

RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(modulus, exponent);   
try {   
     KeyFactory keyFactory = KeyFactory.getInstance("RSA");   

     PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);   
} catch (Exception e) {   
     e.printStackTrace();   
} 
Zimmermann answered 5/7, 2012 at 16:16 Comment(1)
The constructor is actually RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent) docs.oracle.com/javase/7/docs/api/java/security/spec/…Gauguin
H
6

I can't think of any good reason you'd need this. But here it is:

static boolean isValidRSAPair(KeyPair pair)
{
  Key key = pair.getPrivate();
  if (key instanceof RSAPrivateCrtKey) {
    RSAPrivateCrtKey pvt = (RSAPrivateCrtKey) key;
    BigInteger e = pvt.getPublicExponent();
    RSAPublicKey pub = (RSAPublicKey) pair.getPublic();
    return e.equals(pub.getPublicExponent()) && 
      pvt.getModulus().equals(pub.getModulus());
  }
  else {
    throw new IllegalArgumentException("Not a CRT RSA key.");
  }
}
Hidebound answered 5/7, 2012 at 16:34 Comment(0)
D
1

As others have noted, if you have a RSA CRT KEY, then you can extract the public key from that. However it is actually not possible to retrieve a public key from a pure private key.

The reason for that is easy: When generating RSA keys, there is actually no difference between the private and the public key. One is choosen to be private, the remaining one is public then.

So if you could compute the public key from a pure private key, you could by Definition compute the private key from the public key...

If you have both, you can actually easily test if they match:

RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
return rsaPublicKey.getModulus().equals( rsaPrivateKey.getModulus() )
  && BigInteger.valueOf( 2 ).modPow(
  rsaPublicKey.getPublicExponent().multiply( rsaPrivateKey.getPrivateExponent() )
    .subtract( BigInteger.ONE ), 
  rsaPublicKey.getModulus() ).equals( BigInteger.ONE );
Disfigurement answered 25/2, 2015 at 15:46 Comment(0)
A
0

If you have an object of type RSAPrivateKey then you need to do two things:

  1. Get the modulus. Easy: privateKey.getModulus()
  2. Compute the public exponent. This is a little tricky but not impossible. See the definition of public exponent. Usually, the public exponent is 65537.

After getting modulus and public exponent, you can follow PeteyB's answer.

Aretina answered 7/7, 2013 at 13:3 Comment(0)
A
0

I finally found the solution :

   public PublicKey generatePublicKey(String privateKey) {

        try {
            KeyFactory kf = KeyFactory.getInstance(ALGORITHM);
            byte[] encodedPv = Base64.getDecoder().decode(privateKey);

            PKCS8EncodedKeySpec keySpecPv = new PKCS8EncodedKeySpec(encodedPv);
            RSAPrivateCrtKey rsaPrivateKey = (RSAPrivateCrtKey) kf.generatePrivate(keySpecPv);


            RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(), rsaPrivateKey.getPublicExponent());

            return kf.generatePublic(publicKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

Firstly, we should convert Base64 private key to Byte[], and we have to found PrivateKey, by using this two lines :

 PKCS8EncodedKeySpec keySpecPv = new PKCS8EncodedKeySpec(encodedPv);
 RSAPrivateCrtKey rsaPrivateKey = (RSAPrivateCrtKey) kf.generatePrivate(keySpecPv);

The tips is to use RSAPrivateCrtKey class, that expose methode rsaPrivateKey.getPublicExponent()

After that we can call

RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(), rsaPrivateKey.getPublicExponent());
return kf.generatePublic(publicKeySpec);

I test this solution by calculate file signature and verify it after generate new public key every time.

Aiguillette answered 5/11, 2023 at 0:32 Comment(0)
P
-4

AFAIK you cannot derive the other key of an RSA key pair, given one key. That would be equivalent to breaking RSA.

For testing a pair, just encrypt something using one key and decrypt it using the other to see if you get the original result back.

Prana answered 5/7, 2012 at 13:33 Comment(5)
thanks so much! can you be a lil more clear about the second answer? do you have the actual java code for doing it?Francinafrancine
I think this is wrong. According to #5244629 you can get public RSA key from the private key.Reddin
MK, do you know how to do it with Java?Francinafrancine
@MK That is because the public key is included in the private key.Seessel
Deriving the publick key from a private key is certainly possible. See my answer.Aretina

© 2022 - 2024 — McMap. All rights reserved.