【问题标题】:Get RSA public key from private key modulus and private exponent从私钥模数和私有指数中获取 RSA 公钥
【发布时间】:2023-03-21 02:02:01
【问题描述】:

我一直在阅读一些 RSA 文献和堆栈溢出问题,但我没有得到明确的答案。

仅给定一个 RSA 私钥模数和私钥,这就是我所拥有的(对于所有与加密相关的操作也足够了),我可以获得相关的公钥模数和公钥吗?

另外,我可以只用这两个参数获得私钥的编码形式吗?我在 java 中尝试了以下操作(java 不是实际的要求),但是支持它的 OpenSSL 引擎失败并出现错误:04000090:RSA 例程:OPENSSL_internal:VALUE_MISSING

@NonNull
public static byte[] getEncodedRsaPrivateKey(@NonNull BigInteger nModulus, @NonNull BigInteger nPrivateExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
    RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(nModulus, nPrivateExponent);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
    return privateKey.getEncoded();
}

我猜这两个问题的答案都是否定的,但我不确定。

【问题讨论】:

    标签: java cryptography rsa private-key public-key


    【解决方案1】:

    一般RSA私钥包含以下数据:

    • n - 半素模数

    • d - 私有指数

    • p & q - n 的质因数

    • e - 公共指数

    至少,私钥必须包含:

    • nd

    所以回答你的问题:

    我可以获得相关的公钥模数吗?

    是的,你已经拥有了。与私钥使用的n 相同。

    我可以得到公共指数吗?

    不知道pq 是不容易的,虽然你可以猜到,它几乎总是一个小的素数,最常见的是365537

    两者都试一下,检查密文是否有效。

    【讨论】:

    • 去看看,一个用于搜索指数的蹩脚的 for 循环起到了作用。谢谢!
    【解决方案2】:

    按照@Woodstock 的指示,我搜索了公共指数并成功了:

    int nPublicExponent;
    boolean bFound = false;
    for (nPublicExponent = 3; nPublicExponent <= 65537; nPublicExponent++) {
        publicKeySpec = new RSAPublicKeySpec(privateKey.getModulus(), new BigInteger(String.valueOf(nPublicExponent)));
        publicKey = rsaKeyFactory.generatePublic(publicKeySpec);
        if (publicKey == null) {
            continue;
        }
        byte[] encryptMessage = testEncrypt("hello", publicKey);
        if (encryptMessage == null) {
            continue;
        }
        String sMessage = testDecrypt(encryptMessage, privateKey);
        if (TextUtils.isEmpty(sMessage)) {
            continue;
        }
        if (TextUtils.equals(sMessage, "hello")) {
            bFound = true;
            break;
        }
    }
    if (!bFound) {
        Utils.DebugLog("Public exponent not found");
    } else {
        Utils.DebugLog("Public exponent found: " + nPublicExponent);
    }
    
    @Nullable
    public static byte[] testEncrypt(String sMessage, PublicKey publicKey) {
        try {
            Cipher encrypt =  Cipher.getInstance("RSA/ECB/PKCS1Padding");
            encrypt.init(Cipher.ENCRYPT_MODE, publicKey);
            return encrypt.doFinal(sMessage.getBytes());
        } catch (Exception ex) {
            return null;
        }
    }
    
    @Nullable
    public static String testDecrypt(byte[] encryptedMessage, Key privateKey) {
        try {
            Cipher decrypt = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            decrypt.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(decrypt.doFinal(encryptedMessage));
        } catch (Exception ex) {
            return null;
        }
    }
    

    【讨论】:

    • 它是 65537。它在 Android 手机上运行了不到一分钟。我记得在 SSL 证书上到处都能看到这个数字,所以我猜它很常见。这个数字可以任意高吧?让这个过程稍微难一些?但是由于它已经需要私钥,所以从安全的角度来看,我想这没有任何意义。
    猜你喜欢
    • 2013-07-15
    • 2012-01-02
    • 1970-01-01
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 2022-11-22
    相关资源
    最近更新 更多