在Java中从私有获取公钥

时间:2011-12-08 16:41:22

标签: java public-key private-key

我记得很久以前用OpenSSL这么做了,但我想知道它是否可能以及如何,我从来没有在java上使用过Cryptography。

3 个答案:

答案 0 :(得分:27)

我们假设我们正在谈论RSA私钥和公钥。然后,如果您使用的是PEM格式文件,那么首先需要将文件中的私钥读入PrivateKey对象:

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

其中File2String类似于:

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

现在,您可以使用以下代码生成相应的PublicKey:

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

致谢:How to get a RSA PublicKey by giving a PrivateKey?

答案 1 :(得分:3)

请确保Eli Rosencruft答案基本正确,但模数和公共指数的顺序不正确!这是正确的陈述:

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

答案 2 :(得分:-7)

您无法直接从另一个生成任一密钥。这在数学上是不可能的。如果您的密钥blob包含两者公钥和私钥,则可以相对轻松地提取其中任何一个。

编辑,2017年:很多年以后对加密的理解要好得多,现在我很清楚这个答案并不是真的正确。

引用维基百科:

  

公钥由模数n和公共(或加密)指数e组成。私钥由模数n和私有(或解密)指数d组成,必须保密。 p,q和λ(n)也必须保密,因为它们可用于计算d。

公共模数n可以计算为p×q。原始私钥中唯一缺少的是e,但是这个值通常被选为65537,如果不是,你仍然可以从d和λ(n)计算e。

但是,许多私钥存储格式实际上包含公共模数n和其他组件,因此您可以直接提取值。

编辑,2018年:仍然为此付出了代价,这是正确的!我将这个答案留下来,这样人们就能明白为什么我本来就错了,并提醒自己将来不要错。