Lucee5.3 RSA Encryption Issues

#1

Try executing the follow code multiple times on TryCF.com under Lucee 5.LATEST

Why is the output not the same? Is RSA supposed to be deterministic?

writeDump(encrypt('4111111111111111', 'MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQB0S7QHU1LXZ13+QHGeH0bH
2djg5Ei1MEoyZvwL7i30Kl/ox7gJjC2TVQeIrWf5HXmXmFRIDzTGVxmlRXii3DoX
N3B54OM8cADKeEqa1MA/EmpAZfSy4GXa2BPKn0vTJar5cQHGw5VoHd2CbLUJx6fd
Up8G4tGHtBRecRd+G4ou7LULZGwzsy+dh0Y5s8ZBsUVfHDcXoCV6subLMtmw9tM7
g5GQssxUP9blW3e/VFGfi9nMf74mNpWHZxemffLoTlH3Haqt7xBV5j0fkrE1MSSA
tqUdOhcgoW/58sPWd3YZwwL7VOAO0dPHve2X7rH11BJOq+LFeET2Tenpk5Mr1VL/
AgMBAAE=', 'rsa'));

What is Lucee 5.3 implementation details regarding RSA ciphers and key sizes?

Key size

  • 512/1024/2048/4096 bit

Cipher

  • RSA
  • RSA/ECB/PKCS1Padding
  • RSA/None/PKCS1Padding
  • RSA/NONE/OAEPWithSHA1AndMGF1Padding
  • RSA/ECB/OAEPWithSHA-1AndMGF1Padding
1 Like
#2

If anyone is curious about the Lucee RSA encryption implementation under the hood.

Appears to be PKCS #8, and doesn’t look there is a way to override to change the cipher. Which would be a nice feature for interoperability with other systems/languages for example PKCS1 or OAEP.



#3

Due to server to server interoperability requirements I was not able to rely on Lucee’s RSA encryption implementation (PKCS 8). Being able to specify the cipher for key generation and encrypt/decrypt is required. The system I was interacting was expecting the encrypted value to have used the PKCS #1 v1.5 cipher algorithm.

Here is how I implemented RSA encryption with Java instead.

private any function encryptCardNumber(required string cardNumber, required string publicKey) {
	var secureRandom = createObject("java", "java.security.SecureRandom").init();
	var cipher = createObject("java", "javax.crypto.Cipher").getInstance("RSA/ECB/PKCS1Padding", "SunJCE"); // This also is equivalent: getInstance("RSA/None/PKCS1Padding", "BC") for BouncyCastle (org.bouncycastle.jce.provider.BouncyCastleProvider)

	// Convert public key from string to java Key object
	// First need to convert raw string to ByteArray
	var publicKeySpec = createObject('java', 'java.security.spec.X509EncodedKeySpec').init(toBinary(arguments.publicKey));
	var keyFactory = createObject('java', 'java.security.KeyFactory').getInstance('RSA');
	var key = keyFactory.generatePublic(publicKeySpec);
	cipher.init(createObject("java", "javax.crypto.Cipher").ENCRYPT_MODE, key, secureRandom);

	return cipher.doFinal(toBinary(toBase64(arguments.cardNumber)));
}
1 Like
#4

did you try the new GenerateRSAkeys() ?

#5

@Zac_Spitzer

That works fine but I had no use for generating RSA keys. And I actually have zero idea of the language of the server API I was interacting with. All I knew was that I was provided with a public key and data was to be encrypted with RSA. And that’s where the mystery began and took some trial and error to solve. I needed finer details to figure out why I was encountering interoperability issues. The API server couldn’t decrypt the ciphertext properly.

I had some implementation examples using same API with JS (JSEncrpyt), PHP (openssl-public_encrypt & Crypt_RSA), and C# (RSA.Encrypt). I ended up digging through the implementations in those languages and they discovered they use commom cipher algorithm PKCS #1 v1.5 so its apples to apples.

With Lucee encryption doesn’t allow you to change the default cipher algorithm (PKCS #8) from what I could tell in the Lucee engine souce code.

Just wanted to share in case anyone ever encounters a similar issue. If the API server language was Lucee 5.3 then there would not be any issues (unless you were working in JS, C#, PHP)

But JS rsa implementations appear to be the commom denominator. Libraries supporting only PKCS #1 v1.5

The cipher should be a parameter in Lucee which exactly match the Java options for most flexibility.

1 Like
#6

time to file a bug!

#7

It probably falls more into feature request. Because it does function properly, just incomplete (limited) implementation in my opinion. And Lucee docs should at least mention the default cipher used (PKCS #8 I believe, I know for sure it isn’t RSA/ECB/PKCS1Padding).

And it looks different providers have different defaults to make it even more confusing.

Supposedly this is bad practice because of ambiguity.

#8

the Lucee docs are user editable, there’s an icon next to each section, improvements are always welcome!

#9

@Zac_Spitzer Great! I was not aware of that. Thanks for the tip!

#10

you can fork the repo (https://github.com/lucee/lucee-docs), check out a local copy and then interactively run a local server using command box, which is a lot nicer than the per fragment approach via the direct links from the live docs.

once you have finished any edits, you can file a PR