46

I have a bse64encoded string Public key from external source (Android Store) and I need to use it to verify signed content. How can I convert the string into an instance of the java.security.PublicKey interface. I am on Java 6 if that makes a difference.

The key is (probably) generated using standard java lib and not bouncy castle (its from a remote team so I am not sure). Their sample code says to use Security.generatePublicKey(base64EncodedPublicKey); but the Security object in standard java has no such method.

Usman Ismail
  • 17,999
  • 14
  • 83
  • 165

6 Answers6

76

Code for the above answer

public static PublicKey getKey(String key){
    try{
        byte[] byteKey = Base64.decode(key.getBytes(), Base64.DEFAULT);
        X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
        KeyFactory kf = KeyFactory.getInstance("RSA");

        return kf.generatePublic(X509publicKey);
    }
    catch(Exception e){
        e.printStackTrace();
    }

    return null;
}
alexis
  • 1,081
  • 1
  • 9
  • 7
  • I was using a similar piece of code, but this is better ;) Also if working on android you could use: byte[] byteKey = Base64.decode(key.getBytes(), Base64.DEFAULT); – tozhan Jul 03 '14 at 22:06
  • @Hooli: It's "android.util.Base64". Anyway, the value of DEFAULT is 0. – nonzaprej Mar 17 '17 at 12:12
  • 6
    Obviously, you can you Base64.getDecoder().decode(bytes) method from java.util. – pzeszko Apr 25 '17 at 19:09
  • 6
    I modified the first line like this to make it work in Java 8 `byte[] byteKey = Base64.getDecoder().decode(key.getBytes());` – mico Jul 26 '18 at 12:36
30

Ok for grins ... try this

  • base64 decode the key data to get a byte array (byte[])
  • Create a new X509EncodedKeySpec using the byte array
  • Get an instance of KeyFactory using KeyFactory.getInstance("RSA") assuming RSA here
  • call the method generatePublic(KeySpec) with the X509EncodedKeySpec
  • Result /should/ be a public key for your usage.
Dave G
  • 9,639
  • 36
  • 41
  • 1
    Had same issue, tried this and got this exception `java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format` – Wafula Samuel Feb 21 '20 at 13:52
  • I get the same exception. I tried removineding the "BEGIN and END CERTIFICATE" and still get the same error. – testing123 Oct 22 '20 at 23:12
  • As this solved for the requestor's situation, please ask a new question on stackoverflow and provide link here. Please provide code examples of what you are doing and utilize an example certificate e.g. http://fm4dd.com/openssl/source/PEM/certs/2048b-rsa-example-cert.pem. Ideally, sign up for a github account and provide a link to the repository containing your exemplar code and test certificate. – Dave G Oct 23 '20 at 11:40
3

Try this....

PublicKey getPublicKey(byte[] encodedKey) throws NoSuchAlgorithmException, InvalidKeySpecException
{
    KeyFactory factory = KeyFactory.getInstance("RSA");
    X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(encodedKey);
    return factory.generatePublic(encodedKeySpec);
}
Rasheed
  • 991
  • 1
  • 12
  • 18
1

Here's a code snippet:

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;

import org.apache.commons.codec.binary.Base64;
try {
    KeyFactory kf = KeyFactory.getInstance("RSA");
    BigInteger modulus = new BigInteger(1, Base64.decodeBase64(this.stringValue("n")));
    BigInteger exponent = new BigInteger(1, Base64.decodeBase64(this.stringValue("e")));
    return kf.generatePublic(new RSAPublicKeySpec(modulus, exponent));
} catch (InvalidKeySpecException var4) {
    throw new InvalidPublicKeyException("Invalid public key", var4);
} catch (NoSuchAlgorithmException var5) {
    throw new InvalidPublicKeyException("Invalid algorithm to generate key", var5);
}
Linesh Mehta
  • 101
  • 1
  • 2
0

Using spongy castle

public static PublicKey getPublicKeyFromString(String key) throws Exception {
    KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    org.spongycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey
            = org.spongycastle.asn1.pkcs.RSAPublicKey.getInstance(decodeB64(key));
    RSAPublicKeySpec keySpec
            = new RSAPublicKeySpec(pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent());
    PublicKey publicKey = keyFactory.generatePublic(keySpec);
    return publicKey;
}
Jacob Abraham
  • 915
  • 9
  • 8
0

you can try this solution:

add this dependency:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

and use this method:

private Key parsePublicKey(String publicKey) throws IOException {
    try (StringReader sr = new StringReader(publicKey)) {
        PEMParser parser = new PEMParser(sr);
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
        SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(parser.readObject());
        return converter.getPublicKey(publicKeyInfo);
    } catch (IOException e) {
        // handle me
    }
}
Ron
  • 254
  • 2
  • 17
Etay Ceder
  • 160
  • 1
  • 9