问题描述
我一直在阅读一些 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();
}
我想这两个问题的答案都是否定的,但我不确定。
解决方法
通常,RSA
私钥包含以下数据:
-
n
- 半素模数 -
d
- 私有指数 -
的质因数p
&q
-n
-
e
- 公共指数
最低限度,私钥必须包含:
-
n
和d
。
回答您的问题:
我可以获得相关的公钥模数吗?
是的,你已经拥有了。它与私钥使用的 n
相同。
我可以获得公共指数吗?
不知道 p
和 q
并不容易,尽管您可以猜到,但它几乎总是一个小素数,最常见的是 3
或 65537
.
两者都试一下,检查密文是否有效。
,按照@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;
}
}