0
votes

I have a gRPC server written in go that serves a public key to a client written in java. The key uses OAEP padding with sha-256 and is received in what I believe to be PEM format as a ByteString.

I am attempting to read in the bytes received and put them into a PublicKey object to be used for decryption

Go Server Snippet:

plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, d.decKey, ciphertext, label)
if err != nil {
    log.Fatalf("Error from decryption: %s\n", err)
}

// H := H'
return plaintext

RSA Key

This is the key that is printed to the console when I do client.getKey().toString()

-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5SuTn/IhVfLpcgEtbkty
ip6ajx8tcVNt862lj24cz/zGEqzD3sDaRaS+9l16l63T/mWutPqyCBWekg9oGK6Z
ni313nJyvMETCY1kc9mj7IB9yNd00eXr+jYJNF92qc3k0IlyxDjD6hE/InlKn1cM
njYOMYhZtsMSQQElIeYsiqOD1k55E4905XP8gh3K5YT8jVBHJHboJiXVqBJ0CQPq
LKYufey+WcX3p5wKKUgycKxB1zgS1BAHJ/l9x6fxDTE85CBIeRyfSXijHgiWGAEY
MDOIRIBpA8MT5q0Mghy9+KryIHNkc+659DAgCjghY8pmyFezF5gDzRpEi+jB5OOT
bQIDAQAB
-----END RSA PUBLIC KEY-----

I have been attempting to parse it as a string, strip "-----BEGIN RSA PUBLIC KEY-----" and "-----END RSA PUBLIC KEY-----" and convert the remaining string to a byte array and then to a PublicKey object

Java code

String key = client.getPublicKey(nonce).getRSAEncryptionKey().toString();
key = key.replace("-----BEGIN RSA PUBLIC KEY-----\n", "");
key = key.replace("-----END RSA PUBLIC KEY-----", "");
byte[] keyBytes = Base64.getDecoder().decode(key); //bytes of key
Cipher cipher_RSA;
        try {
            cipher_RSA = Cipher.getInstance("RSA");
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pk = keyFactory.generatePublic( spec);

            cipher_RSA.init(Cipher.ENCRYPT_MODE, pk); 
            return cipher_RSA.doFinal(message);
        }catch(Exception e){}

This keeps resulting in "Illegal base64 character". I assume this is to do with the fact the key uses OAEP padding. However when I change the instance of the key factory/cipher to "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING" I receive this error:

java.security.NoSuchAlgorithmException: RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING KeyFactory not available
1
If you had examined the line causing the "Illegal base64 character" you'd see it was from the base64 decoder, so it couldn't possibly have anything to do with "OAEP padding". The error is caused by the white space (newlines) in the String. Simply get rid of them. - President James K. Polk
@JamesKPolk That was my initial thought, however, as far as I'm aware the key should be valid base64. I only assumed it was to do with the padding as I have run out of ideas of what could be the problem. - Dom Fraise
OAEP is a padding for RSA encryption; an RSA key is the same regardless of which operations with which paddings it is or wll be used, and therefore the KeyFactory doesn't implement any paddings (or modes either). - dave_thompson_085

1 Answers

2
votes

Different base64 decoders have different rules about whether to throw an exception upon encountering an illegal base64 character or whether to simply ignore the character. White space, including the newline, is not a valid base64 character. To correct your error you must simply remove the newlines from the PEM public key string prior to base64 decoding.

key = key.replace("-----BEGIN RSA PUBLIC KEY-----\n", "");
key = key.replace("-----END RSA PUBLIC KEY-----", "");
// add the following line  
key = key.replace("\n", "");

Note: this is oversimplified in that it assumes that '\n' will be the line separator character. You could also add replacements to other common line separator character sequences. Make sure you order the replacements by length, with longest first and the shortest last.