【问题标题】:Get public key from private in Java从Java中的私有获取公钥
【发布时间】:2012-01-16 02:13:11
【问题描述】:

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

【问题讨论】:

标签: java public-key private-key


【解决方案1】:

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

编辑,2017 年:多年后对加密有了更好的理解,现在我很清楚这个答案并不正确。

引用维基百科:

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

公共模数 n 可以计算为 p × q。原始私钥中唯一缺少的是 e,但该值通常选择为 65537,如果没有,您仍然可以根据 d 和 λ(n) 计算 e。

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

编辑,2018 年: 仍然对此表示反对,这是正确的!我将留下这个答案,以便人们可以看到我最初错的原因,并提醒自己将来不要错。

【讨论】:

  • 假设密钥是 RSA 密钥,并且以标准方式存储,库 (openssl) 所指的“私钥”包括公钥。这不是关于“生成”,而是更多关于“提取”/“访问”。
  • @Romain - 这就是我在回答中所说的:)
  • 确实如此。尽管在这种情况下您没有回答问题- OP 询问“如何”“相对轻松地提取其中一个”:)
  • 这个答案是错误的。可以从私钥生成 RSA 公钥。
  • 确实如此。看来六年前我对 RSA 的理解是相当有缺陷的。我已经对其进行了编辑以包含正确的答案。
【解决方案2】:

假设我们正在讨论 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?

【讨论】:

  • 公钥规范的参数顺序是否正确?不应该先取模吗?
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 2021-05-08
    • 1970-01-01
    • 2023-03-21
    • 2012-01-02
    • 1970-01-01
    相关资源
    最近更新 更多