如何通过提供 PrivateKey 来获得 RSA PublicKey?

Posted

技术标签:

【中文标题】如何通过提供 PrivateKey 来获得 RSA PublicKey?【英文标题】:How to get a RSA PublicKey by giving a PrivateKey? 【发布时间】:2012-07-05 22:01:12 【问题描述】:

我正在寻找可以获取 RSA PrivateKey 并返回正确 RSA PublicKey 的 Java 函数?

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

【问题讨论】:

保持冷静。论坛与实时聊天完全不同。请始终牢记,用户在这里是自愿的,并且可以随时随地进行。 定义“有效”的含义。 除了给出的答案之外,如果您始终可以执行签名/验证(对任何值)以查看键是否匹配。请注意,有时这很麻烦,例如如果为私钥保留使用计数(某些 HSM 和智能卡会这样做)。仅比较模数或模数上的散列也很好,每个密钥对的模数应该是唯一的。不需要公共指数。 【参考方案1】:

AFAIK 给定一个密钥,您无法派生 RSA 密钥对的另一个密钥。这相当于破坏了 RSA。

为了测试一对,只需使用一个密钥加密某些内容并使用另一个密钥解密,看看您是否能得到原始结果。

【讨论】:

非常感谢!你能对第二个答案更清楚一点吗?你有实际的 Java 代码吗? 我认为这是错误的。根据***.com/questions/5244129/…,您可以从私钥中获取公钥。 MK,你知道用Java怎么做吗? @MK 那是因为公钥包含在私钥中。 从私钥派生公钥当然是可能的。看我的回答。【参考方案2】:

如果您将私钥作为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();   
 

【讨论】:

构造函数其实是 RSAPublicKeySpec(BigIntegermodal,BigInteger publicExponent)docs.oracle.com/javase/7/docs/api/java/security/spec/…【参考方案3】:

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

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】:

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

    获取模数。简单:privateKey.getModulus() 计算公共指数。这有点棘手,但并非不可能。请参阅definition of public exponent。通常,公共指数是65537

得到模数和公共指数后,你可以按照 PeteyB 的回答。

【讨论】:

【参考方案5】:

正如其他人所指出的,如果您有 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 );

【讨论】:

以上是关于如何通过提供 PrivateKey 来获得 RSA PublicKey?的主要内容,如果未能解决你的问题,请参考以下文章

如何存储/检索 RSA 公钥/私钥

Java:如何从字符串生成 PrivateKey?

将 JSON 公钥/私钥对转换为 rsa.PrivateKey 和 rsa.PublicKey

rsa非对称加密-python实现

php RSA公钥私钥加解密和验证用法

Spring Cloud Config - RSA简介以及使用RSA加密配置文件