MA1
MA1

Reputation: 1086

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

I have a String public key and I'm trying to convert it to Java PublicKey object using the code below, however I don't know the algorithm that was used to generate this public key. Is there anyway to extract the algorithm name from the String public key?

 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);

Upvotes: 2

Views: 2114

Answers (2)

dave_thompson_085
dave_thompson_085

Reputation: 39020

Firat an aside: what you have is one 'String' (textual) representation of a publickey, specifically the base64 encoding of an ASN.1 structure SubjectPublicKeyInfo defined in X.509 and PKIX, and used by default in Java crypto as noted in the doc for X509EncodedKeySpec but explained more fully in Key. There are many other 'string' representations of publickeys which are quite different, and not so easily usable in Java.

Java actually has classes for this and related structures -- and uses them when processing an X.509 certificate which includes SPKI -- but they are internal and undocumented, and while in years past it was possible to just call internal classes Java (Oracle) is now on a massive effort to progressively make this more difficult or impossible, so I can't recommend it.

If you can use third-party code specifically BouncyCastle it is easy. The closest way to what you asked for is to parse the SPKI and get the algorithm 'name' from it -- but this is in the form of an ASN.1 Object Identifier aka OID, not the name Java normally uses. If you use the BouncyCastle provider (bcprov*.jar) for the KeyFactory call, it has an alias mapping for this OID to the normal name:

    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());

However, if you use the bcpkix*.jar library (which depends on bcprov being available but not necessarily registered) it handles the OID-name mapping with any provider (like the normal SunEC) and manages the KeyFactory for you in one step:

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

Upvotes: 2

brighthammer
brighthammer

Reputation: 51

I am not sure about it but I think it is the keyspec you give that has the algorithm. See getAlgorithm() method here: https://docs.oracle.com/javase/8/docs/api/index.html?java/security/KeyFactory.html

Also here (https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#KeyFactoryEx) I have seen this:

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).

Upvotes: 0

Related Questions