21

I remember do this long time ago with OpenSSL, but I want to know if it's possible and how, I've never used Cryptography on java.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
BRabbit27
  • 6,333
  • 17
  • 90
  • 161
  • See http://stackoverflow.com/questions/11345346/how-to-get-a-rsa-publickey-by-giving-a-privatekey and below answer based on answer to that question. – Eli Rosencruft Oct 10 '12 at 07:12

3 Answers3

42

The assumption is that we are talking about RSA private and Public keys. Then, if you are working from a PEM format file, then first you need to read the private key from the file into a PrivateKey object:

    public PrivateKey readPemRsaPrivateKey(String pemFilename) throws
            java.io.IOException,
            java.security.NoSuchAlgorithmException,
            java.security.spec.InvalidKeySpecException
    {
            String pemString = File2String(pemFilename);

            pemString = pemString.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
            pemString = pemString.replace("-----END RSA PRIVATE KEY-----", "");

            byte[] decoded = Base64.decodeBase64(pemString);

            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
            KeyFactory kf = KeyFactory.getInstance("RSA");

            return kf.generatePrivate(keySpec);
    }

where File2String is something like:

    private static String File2String(String fileName) throws
            java.io.FileNotFoundException, java.io.IOException
    {
            File file = new File(fileName);

            char[] buffer = null;

            BufferedReader bufferedReader = new BufferedReader(new FileReader(file));

            buffer = new char[(int)file.length()];

            int i = 0;
            int c = bufferedReader.read();

            while (c != -1) {
                    buffer[i++] = (char)c;
                    c = bufferedReader.read();
            }
            return new String(buffer);
    }

Now you can generate the corresponding PublicKey with code like this:

    import java.security.interfaces.RSAPrivateCrtKey;
    import java.security.spec.RSAPublicKeySpec;

...

    PrivateKey myPrivateKey = readPemRsaPrivateKey(myPrivateKeyPemFileName);
    RSAPrivateCrtKey privk = (RSAPrivateCrtKey)myPrivateKey;

    RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(), privk.getPublicExponent());

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey myPublicKey = keyFactory.generatePublic(publicKeySpec);

Credits: How to get a RSA PublicKey by giving a PrivateKey?

Community
  • 1
  • 1
Eli Rosencruft
  • 7,232
  • 1
  • 19
  • 17
7

Please make sure that Eli Rosencruft answer is basically correct, but the order of the modulus and the public exponent are incorrect! This is the correct statement:

RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(), privk.getPublicExponent());
caschulz88
  • 91
  • 1
  • 4
-10

You cannot generate either key directly from the other. It is mathematically impossible. If you had a key blob that contained both the public and private keys, you could extract either one of them with relative ease.

EDIT, 2017: Many years and a much better understanding of crypto later, and it's now clear to me that this answer isn't really correct.

To quote Wikipedia:

The public key consists of the modulus n and the public (or encryption) exponent e. The private key consists of the modulus n and the private (or decryption) exponent d, which must be kept secret. p, q, and λ(n) must also be kept secret because they can be used to calculate d.

The public modulus n can be computed as p × q. The only thing missing from a raw private key is e, but this value is usually selected as 65537, and if not you can still compute e from d and λ(n).

However, many private key storage formats actually contain the public modulus n alongside the other components, so you can just do a direct extraction of the values.

EDIT, 2018: Still getting downvotes for this, and rightly so! I'm leaving this answer up so people can see why I was originally wrong, and to remind myself not to be wrong in future.

Polynomial
  • 27,674
  • 12
  • 80
  • 107
  • 6
    Assuming the key is an RSA key, and it's stored in a standard way, the "private key" as meant by the library (openssl) *includes* the public key. It's not about "generating" but more about "extracting"/"accessing". – Romain Dec 08 '11 at 16:43
  • 1
    @Romain - Which is what I said in my answer :) – Polynomial Dec 08 '11 at 16:44
  • 2
    Indeed. Though in that case you're not answering the question - the OP asks "how" you do "extract either one with relative ease" :) – Romain Dec 08 '11 at 16:46
  • @Romain ah sorry. Yes indeed it is RSA and it was created with OpenSSL. I know I cannot "create" one key from the other, what I meant is how to extract it or if it's possible to extract it. Thanks for your responses! – BRabbit27 Dec 08 '11 at 16:46
  • Depends on what he's got. If it's a CSR or PEM, I'm pretty sure they're plaintext. If it's a plain key, then it depends on what *type* of key it is. – Polynomial Dec 08 '11 at 16:47
  • @BRabbit27 - Try opening up the key file in Notepad (or equivilent). Some key files are plaintext and contain the two keys as distinct Base64 blobs. – Polynomial Dec 08 '11 at 16:48
  • 2
    This answer is just wrong. Its possible to generate an RSA public key from the private key. – tObi Feb 20 '17 at 18:49
  • 2
    Indeed. It appears that six years ago my understanding of RSA was rather flawed. I have edited it to include the correct answer. – Polynomial Feb 20 '17 at 20:57
  • 1
    @Polynomial not just RSA. It's also possible to compute an EC public key from the private key. It's not impossible that some asymmetric scheme might be invented where public and private keys are both derived from some third value which is discarded, but I'm not aware of any. In all common schemes the public key is computed from the private key plus any public scheme parameters (e.g. choice of elliptic curve). – divegeek Jan 07 '19 at 17:23
  • It seems odd that this still present after all these years since even the author has said it is wrong. Can the **selected answer** be changed to a valid answer? – PatS Apr 08 '23 at 12:54