Java – How to load an RSA public key from a String for signature verification in Java?

How to load an RSA public key from a String for signature verification in Java?… here is a solution to the problem.

How to load an RSA public key from a String for signature verification in Java?

I have the following public key, which is stored in text form in a database (PostgresSQL). It is a string, in java:

-----BEGIN RSA PUBLIC KEY-----     

I don’t know how this key is generated, sorry. I was told to take this key and verify the signature of another string I called an “object”. I was told that the algorithm I have to use to validate the “object” is SHA256withRSA.

So, I wrote the following java method to read key

private PublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException {
    publicKey = publicKey.replaceAll("\\n", "");
    publicKey = publicKey.replace("-----BEGIN RSA PUBLIC KEY-----", "");
    publicKey = publicKey.replace("-----END RSA PUBLIC KEY-----", "");
    publicKey = publicKey.trim();
    byte[] keyDecoded = Base64.getDecoder().decode(publicKey.getBytes());
    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(keyDecoded);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PublicKey pubKey = kf.generatePublic(publicSpec);
    return pubKey;

The point is that I get the following exception: IOException: algid parse error, not
a sequence

I read a lot of questions in stackoverflow. Other users write code that is very similar (sometimes the same) to mine. So I absolutely don’t understand why it doesn’t work for me. Other developers (colleagues) are doing the same thing in php and it works great, so I’ll give up the assumption of a wrong public key. Maybe I don’t have a clear understanding of the process? Do you have any clues?

I also tried using the BouncyCaSTLe library to solve this problem, as suggested here , but I get the same exception. Here is the code I wrote:

private static PublicKey getPublicKey(String publicKey)
        throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
    Security.addProvider(new BouncyCastleProvider());
    PemReader pp = new PemReader(new StringReader(publicKey));
    PemObject pem = pp.readPemObject();
    byte[] content = pem.getContent();

X509EncodedKeySpec spec = new X509EncodedKeySpec(content);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);


You cannot load the key using X509EncodedKeySpec. According to its JavaDoc documentation It requires the following format:

SubjectPublicKeyInfo ::= SEQUENCE {
   algorithm AlgorithmIdentifier,
   subjectPublicKey BIT STRING }

Instead, your key looks different. I used the data from your post, converted it to hexadecimal data and posted it onlineASN.1 decoder .

The output is this:

SEQUENCE (2 elem)
  INTEGER (4096 bit) 873481340827968071893572683200799871431146795599597693981565010037737...
  INTEGER 65537

As you probably recognize, your key does not contain an AlgorithmIdentifier, so it cannot be loaded using X509EncodedKeySpec.

My suggestion is to use the BouncyCaSTLe library and its PEMParser class to load this key:

File pemFile = new File("test.pem");
try (PEMParser pp = new PEMParser(new InputStreamReader(new FileInputStream(pemFile)))) {
    SubjectPublicKeyInfo subjPubKeyInfo = (SubjectPublicKeyInfo) pp.readObject();
    RSAKeyParameters rsa = (RSAKeyParameters) PublicKeyFactory.createKey(subjPubKeyInfo);

RSAPublicKeySpec rsaSpec = new RSAPublicKeySpec(rsa.getModulus(), rsa.getExponent());
    KeyFactory kf = KeyFactory.getInstance("RSA"); publicKey = kf.generatePublic(rsaSpec);

Or you can manually convert the key to PKCS#8 format via openssl.

Related Problems and Solutions