【问题标题】:Creating RSA keys from known parameters in Java从 Java 中的已知参数创建 RSA 密钥
【发布时间】:2011-01-02 16:08:28
【问题描述】:

我正在努力实施 Bing Cashback。为了验证来自 Bing 的传入请求是否有效,它们提供了签名。签名是使用 RSA 加密的 url 的 160 位 SHA-1 哈希。

Microsoft 提供了 RSA“公钥”、模数和指数,我应该用它来解密散列。

有没有办法像微软所说的那样创建解密散列所需的 Java 密钥对象?

我能找到的所有东西都会自动创建 RSA 密钥对,因为 RSA 应该是这样工作的。如果可能的话,我真的很想使用 Java 对象,因为这显然比手动编码的解决方案更可靠。

他们提供的示例代码位于 .NET 中,并使用 .NET 库函数来验证哈希。特别是 RSACryptoServiceProvider.VerifyHash()

【问题讨论】:

    标签: java rsa encryption bing


    【解决方案1】:

    这样的事情应该可以解决问题:

      private PublicKey convertPublicKey(String publicKey) throws Exception{
        PublicKey pub = null;
    
        byte[] pubKey = Hex.decodeHex(publicKey.toCharArray());
        X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        pub = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
    
        return pub;
      }
    

    假设公钥以十六进制字符串的形式给出,您需要Apache Commons Codec library

    如果您有其他格式的密钥,请尝试KeyFactory 了解更多信息。

    【讨论】:

    • 我必须检查一下我们是否有那个库,或者我们是否可以获得它。此外,Cip​​her 对象是否会在 DECRYPT_MODE 中使用公钥?这对我来说似乎很倒退。
    • 如果您使用的是 Sun JRE,但不是 IBM 版本。巧合的是,使用 Bouncy Castle 加密提供程序的 IBM JRE 也可以工作。
    • 它可能看起来倒退,但您所做的实际上是解密“签名”哈希。解密后,您计算的哈希值和 Microsoft 提供给您的哈希值应该匹配。
    • ...但这是埃里克森正确做法的艰难方式。
    • 我上面的代码是完全正确的(并且有效)。如果原始海报的密钥是十六进制字符串(而不是模数/指数格式),这是唯一能真正帮助他的答案。具有讽刺意味的是,我是一个没有得分的人。
    【解决方案2】:

    使用 java.security.spec.RSAPublicKeySpec。它可以从指数和模数构造一个键。然后使用 java.security.KeyFactory.generatePublic() 和 key spec 作为参数。

    【讨论】:

      【解决方案3】:
      RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
      KeyFactory factory = KeyFactory.getInstance("RSA");
      PublicKey pub = factory.generatePublic(spec);
      Signature verifier = Signature.getInstance("SHA1withRSA");
      verifier.initVerify(pub);
      verifier.update(url.getBytes("UTF-8")); // Or whatever interface specifies.
      boolean okay = verifier.verify(signature);
      

      【讨论】:

      • Cipher 会在 DECRYPT_MODE 中使用公钥吗?
      • 是的,大多数提供者的 RSA 密码实现将接受用于解密的公钥。他们甚至会检查正确的填充。但是,最好使用Signature 实例。我将更新我的答案以进行演示。
      • FWIW,为ne 创建必要的BigInteger,如果你有base-64 格式的两个值(这在OpenID JWKS 响应等中很常见),请使用new BigInteger(1, org.springframework.util.Base64Utils.decodeFromUrlSafeString((String) key.get("n")))(或另一个支持 URL 安全解码的 base-64 库)- 强调将 1 作为 BigIntegersignum
      猜你喜欢
      • 2020-12-26
      • 1970-01-01
      • 2018-02-03
      • 2019-05-24
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2013-04-04
      • 1970-01-01
      相关资源
      最近更新 更多