简体   繁体   English

从私钥模数和私钥指数中获取 RSA 公钥

[英]Get RSA public key from private key modulus and private exponent

I have been reading some RSA literature and stack overflow questions, but I didn't get a definitive answer.我一直在阅读一些 RSA 文献和堆栈溢出问题,但没有得到明确的答案。

Given a RSA private key modulus and private exponent only, which is all I have (and also enough for all crypto related operations), can I get the associated public key modulus and public exponent?仅给定 RSA 私钥模数和私有指数,这就是我所拥有的(也足以用于所有与加密相关的操作),我可以获得相关的公钥模数和公共指数吗?

Also, can I get the encoded form of the private key with only those two parameters?另外,我可以仅使用这两个参数获取私钥的编码形式吗? I've tried the following in java (java is not an actual requeriment), however the OpenSSL engine that backs it fails with error:04000090:RSA routines:OPENSSL_internal:VALUE_MISSING我在 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();
}

I guess the answer is no for both questions, but I'm not sure.我想这两个问题的答案都是否定的,但我不确定。

Generally the RSA private key contains the following data:通常RSA私钥包含以下数据:

  • n - semiprime modulus n - 半素模数

  • d - private exponent d - 私有指数

  • p & q - prime factors of n p & q - n质因数

  • e - public exponent e - 公共指数

At a minimum , the private key must contain:至少,私钥必须包含:

  • n and d . nd

So to answer your questions:所以回答你的问题:

can I get the associated public key modulus?我可以得到相关的公钥模数吗?

Yep, you already have it.是的,你已经拥有了。 It's the same n used by the private key.它与私钥使用的n相同。

can I get the public exponent?我可以得到公共指数吗?

Not easily without knowing p and q , though you can guess at it, it's nearly always a small prime, most commonly either 3 or 65537 .不知道pq并不容易,尽管您可以猜测它,但它几乎总是一个小素数,最常见的是365537

Try both and check if ciphertext is valid.尝试两者并检查密文是否有效。

As instructed by @Woodstock, I searched for the public exponent and succeeded:按照@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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM