1

I'm having some trouble with using a public key from Java to encrypt within NodeJS.

I've created an RSA key within keytool and output the public key as a base64 encoded string.

Base64.Encoder encoder = Base64.getEncoder();
byte[] pubKeyBytes = publicKey.getEncoded();
String pubKeyBase64 = encoder.encodeToString(pubKeyBytes);

I then took the the base64 encoded public key, wrapped it in -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- and used it to encrypt, then base64 encode a string within node.

const encryptedBuffer = crypto.publicEncrypt(encodedPublicKey, buffer);
const encryptedEncodedText = encryptedBuffer.toString("base64");

When I try to decrypt the encryptedEncodedText (base64 decoding first) within Java, it throws a BadPadding exception. Interestingly, if I export the private key to a PEM, Node can't decrypt with it either.

Any help would be appreciated!

3
  • See this: stackoverflow.com/questions/8750780/… Commented Jul 14, 2018 at 14:45
  • Yeah, I've tried that answer. I'm not sure what I'm missing from that post. Commented Jul 14, 2018 at 14:51
  • 1
    Also, if I use an OpenSSL public / private key, the encryption / decryption works fine in node, so I'm doing something wrong, or misunderstanding something from the Java side. Commented Jul 14, 2018 at 15:00

2 Answers 2

2

After much searching and testing, it turned out to be a padding issue.

The public key provided to Node did was not being passed a passphrase, so it defaulted to RSA_PKCS1_OAEP_PADDING as per the documentation:

crypto.publicEncrypt

When decrypting on the Java side, it is necessary to inform Java of that padding as follows:

Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPPadding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);

This fixed the issue, and allowed messages to be exchanged between Java and NodeJS.

Sign up to request clarification or add additional context in comments.

Comments

1

I tried to reproduce your problem. For me, it works fine. I suspect the only problematic step can be when you are creating the PEM file manually. Be sure to:

  • If you are copying the key string from any console, remove unwanted characters from the beginning and/or end.
  • And a new line character (\n) after -----BEGIN PUBLIC KEY----- and before -----END PUBLIC KEY-----.

like below:

var key = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqwEldwNI5s1LkUzwyQZkPQQFpgtj29W7RcHgdwAbUOe31Q8bybAgzg5cUMqdIQlQHq6S5dxsSJBTDCZozSu+pxtKqRLz0JjtCTZD5gS+CJR9DlXH5GgJt+KDiO6olbKiVsP/tsMPgRCFKUMiMKU+dA06dwrUqJlC1k/JzuYVrbwIDAQAB\n-----END PUBLIC KEY-----"

var plaintext = "hello world"
var buffer = new Buffer(plaintext, "utf8")
console.log(crypto.publicEncrypt(key, buffer))

To avoid all these issues, you can directly generate PEM file from Java using the bouncycastle library.

4 Comments

Thanks for the tip, I'll give it a try!
So something to note, it encrypts in node just fine, when I try to decrypt what I encrypted in node within the Java code, it doesn't work.
Doesn't work as in? seems like encoding related problem.
When I try to decrypt, it gives me a bad padding exception, it very well could be a encoding problem, I'm not sure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.