如何从字符串 public 密钥中提取 public 密钥算法?

How to extract the public key algorithm from a String public key?

我有一个字符串 public 密钥,我正在尝试使用下面的代码将其转换为 Java PublicKey 对象,但是我不知道用于生成此密钥的算法public 键。无论如何从字符串 public 键中提取算法名称?

 String stringPubKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmRk7MSZQCX2u4UIQgVzma1JEo3yASVafls/5nw/V9T6e5EbsK64MM0KhsPH9aK/aElRt1+Rxtd1AsHVvsQJjKw==";
 byte[] publicBytes = Base64.getDecoder().decode(stringPubKey);
 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
 KeyFactory keyFactory = KeyFactory.getInstance(algorithmName);
 PublicKey publicKey = keyFactory.generatePublic(keySpec);

我不确定,但我认为是您提供的密钥规范具有算法。请参阅此处的 getAlgorithm() 方法:https://docs.oracle.com/javase/8/docs/api/index.html?java/security/KeyFactory.html

也在这里(https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#KeyFactoryEx)我看到了这个:

Algorithm Parameters Classes Like Keys and Keyspecs, an algorithm's initialization parameters are represented by either AlgorithmParameters or AlgorithmParameterSpecs. Depending on the use situation, algorithms can use the parameters directly, or the parameters might need to be converted into a more portable format for transmission or storage.

A transparent representation of a set of parameters (via AlgorithmParameterSpec) means that you can access each parameter value in the set individually. You can access these values through one of the get methods defined in the corresponding specification class (e.g., DSAParameterSpec defines getP, getQ, and getG methods, to access p, q, and g, respectively).

In contrast, the AlgorithmParameters class supplies an opaque representation, in which you have no direct access to the parameter fields. You can only get the name of the algorithm associated with the parameter set (via getAlgorithm) and some kind of encoding for the parameter set (via getEncoded).

顺便说一句:你所拥有的是公钥的 one 'String' (文本)表示,特别是 ASN.1 结构 SubjectPublicKeyInfo 中定义的 base64 编码X.509 和 PKIX,默认情况下在 Java 加密中使用,如 X509EncodedKeySpec but explained more fully in Key 的文档中所述。公钥还有许多其他 'string' 表示,它们非常不同,并且在 Java.

中不太容易使用

Java 实际上有 类 用于此结构和相关结构——并在处理 X.509 certificate 时使用它们 includes SPKI——但是它们是内部的并且没有记录,虽然在过去的几年里可以只调用内部 类 Java (Oracle) 现在正在努力逐步使这更难或不可能,所以我不推荐它。

如果能具体使用第三方代码BouncyCastle就容易了。最接近您要求的方法是解析 SPKI 并从中获取算法 'name'——但这是 ASN.1 对象标识符 aka OID 的形式,而不是名称 Java通常使用。 如果您使用 BouncyCastle provider (bcprov*.jar) 进行 KeyFactory 调用,它具有此 OID 的别名映射到正常名称:

    String stringPubKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmRk7MSZQCX2u4UIQgVzma1JEo3yASVafls/5nw/V9T6e5EbsK64MM0KhsPH9aK/aElRt1+Rxtd1AsHVvsQJjKw==";
    byte[] publicBytes = Base64.getDecoder().decode(stringPubKey);
    
    String oid = org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(publicBytes)
            .getAlgorithm().getAlgorithm().toString(); /* yes, two different .getAlgorithm() ! */
    PublicKey pk = KeyFactory.getInstance(oid, new org.bouncycastle.jce.provider.BouncyCastleProvider())
            .generatePublic(new X509EncodedKeySpec(publicBytes));
    System.out.println(oid + " -> " + pk.getAlgorithm());

但是,如果您使用 bcpkix*.jar 库(这取决于 bcprov 是否可用但不一定已注册),它会处理与 any 提供商的 OID 名称映射(像普通的 SunEC) 并一步为您管理 KeyFactory:

    // setup as above
    /*PublicKey*/ pk = new org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter().getPublicKey(
            org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(publicBytes));
    System.out.println(pk.getAlgorithm());