DasDas
DasDas

Reputation: 581

How to get a RSA PublicKey by giving a PrivateKey?

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?

Upvotes: 12

Views: 14692

Answers (6)

Zakariae BEN ALLAL
Zakariae BEN ALLAL

Reputation: 92

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.

Upvotes: 0

Steffen Heil
Steffen Heil

Reputation: 4346

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

Upvotes: 1

Petey B
Petey B

Reputation: 11569

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

Upvotes: 13

HRJ
HRJ

Reputation: 17807

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.

Upvotes: 0

erickson
erickson

Reputation: 269857

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

Upvotes: 6

Sfynx
Sfynx

Reputation: 365

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.

Upvotes: -4

Related Questions