问题 如何通过提供PrivateKey来获取RSA PublicKey?


我正在寻找一个Java函数,它将获得一个RSA PrivateKey并将返回正确的RSA PublicKey?

或者,是否有一个函数可以告诉我们RSA PrivateKey / PublicKey是否有效?


3120
2017-07-05 13:28


起源

保持酷。一个论坛与实时聊天完全不同。请始终牢记用户随心所欲,随时随地都可以。 - reporter
:)生病记住:) :) :) - DasDas
用“有效”来定义你的意思。 - James K Polk
除了给出的答案,如果你总是可以执行签名/验证(在任何值上)以查看密钥是否匹配。请注意,偶尔这很麻烦,例如如果为私钥保留了使用次数(某些HSM和智能卡都有)。仅比较模数或模数上的散列也很好,模数对于每个密钥对应该是唯一的。不需要公众指数。 - Maarten Bodewes


答案:


如果您将私钥作为 RSAPrivateCrtKey 对象,你可以获得公共指数以及模数。

然后你可以像这样创建公钥:

RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(modulus, exponent);   
try {   
     KeyFactory keyFactory = KeyFactory.getInstance("RSA");   

     PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);   
} catch (Exception e) {   
     e.printStackTrace();   
} 

10
2017-07-05 16:16



构造函数实际上是RSAPublicKeySpec(BigInteger modulus,BigInteger publicExponent) docs.oracle.com/javase/7/docs/api/java/security/spec/... - Eric Woodruff
@Eric Woodruf,更新,谢谢。 - Petey B


我想不出你需要这个的任何好理由。但这里是:

static boolean isValidRSAPair(KeyPair pair)
{
  Key key = pair.getPrivate();
  if (key instanceof RSAPrivateCrtKey) {
    RSAPrivateCrtKey pvt = (RSAPrivateCrtKey) key;
    BigInteger e = pvt.getPublicExponent();
    RSAPublicKey pub = (RSAPublicKey) pair.getPublic();
    return e.equals(pub.getPublicExponent()) && 
      pvt.getModulus().equals(pub.getModulus());
  }
  else {
    throw new IllegalArgumentException("Not a CRT RSA key.");
  }
}

4
2017-07-05 16:34





正如其他人所说,如果你有 RSA CRT KEY,然后你可以从中提取公钥。然而事实上  可以从纯私钥中检索公钥。

原因很简单:生成RSA密钥时,私钥和公钥之间实际上没有区别。一个选择是私人的,剩下的一个是公开的。

因此,如果您可以从纯私钥计算公钥,您可以通过定义从公钥计算私钥...

如果你有两者,你可以很容易地测试它们是否匹配:

RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
return rsaPublicKey.getModulus().equals( rsaPrivateKey.getModulus() )
  && BigInteger.valueOf( 2 ).modPow(
  rsaPublicKey.getPublicExponent().multiply( rsaPrivateKey.getPrivateExponent() )
    .subtract( BigInteger.ONE ), 
  rsaPublicKey.getModulus() ).equals( BigInteger.ONE );

1
2018-02-25 15:46





这绝对是错的!您始终可以从私钥获取公钥,但您永远无法从公钥获取私钥。这就是RSA不对称算法的原因!


0
2018-04-05 11:27



实际上,它称为非对称算法,因为发送方和接收方不使用相同的密钥,而不是因为您生成密钥的方式。 - B T


如果你有一个类型的对象 RSAPrivateKey 那么你需要做两件事:

  1. 获得模数。简单: privateKey.getModulus()
  2. 计算公共指数。这有点棘手,但并非不可能。见 公共指数的定义。通常,公共指数是 65537

获得模数和公共指数后,您可以按照PeteyB的答案。


0
2017-07-07 13:03





AFAIK如果给出一个密钥,则无法导出RSA密钥对的其他密钥。这相当于打破RSA。

对于测试一对,只需使用一个密钥加密某个东西,然后使用另一个密钥对其进行解密,看看是否得到了原始结果。


-3
2017-07-05 13:33



非常感谢!对于第二个答案,你能更清楚吗?你有实际的Java代码吗? - DasDas
我认为这是错误的。根据 stackoverflow.com/questions/5244129/... 您可以从私钥获取公共RSA密钥。 - MK.
MK,你知道如何用Java做到这一点吗? - DasDas
@MK这是因为公钥包含在私钥中。 - Mark Rotteveel
从私钥中获取publick键当然是可能的。看到我的回答。 - HRJ