openssl_public_encrypt for Ensemble

Primary tabs

Hello.

We have to call a service, and we have to encrypt the request using a public key. We have an example of how to make the call in PHP. Also we have the public key and all the parameters that we need. The example in PHP is this (it uses openssl):

$url = "https://XXXXX/";
$json = '{"api_key":"XXXXX", "id":"1"}';
$jsonEncrypt, = '';
$publicKey = file_get_contents("public.key");
openssl_get_publickey($publicKey);
openssl_public_encrypt($json,  $jsonEncrypt,  $publicKey);
$jsonEncrypt = base64_encode($jsonEncrypt);

We need to do the same in Ensemble. I have tried to use this:

set IV = ""
set file = ##class(%FileCharacterStream).%New()
set file.Filename = "public.key"
set key = file.Read(file.Size)
set sc = $System.Encryption.AESCBCEncryptStream(json, .jsonEncrypt, key, IV)
if ($$$ISOK(sc)) {
        set jsonEncBase64 = $System.Encryption.Base64Encode(jsonEncrypt.Read(jsonEncrypt.Size))
}

But it doesn't work. The base64 that I get using this is not correctly encoded. Is this the way to encrypt using a public.key? How should I do it? Is there a way to use openssl_public_encrypt or something similar in Ensemble?

Thank you very much in advance.

Replies

Hi Laura.

First question -- what algorithm does openssl_public_encrypt use?

PHP reference [1] and source code [2] says that this is RSA.

So in Ensemble you can use $system.Encryption.RSAEncrypt() [3]

Important thing to note about RSA encryption, is that length of the plaintext can not be greater than the length of the modulus of the RSA public key contained in the certificate minus 42 bytes.

[1] https://www.php.net/manual/en/function.openssl-public-encrypt.php
[2] https://github.com/php/php-src/blob/master/ext/openssl/openssl.c#L5549
[3] https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...

Thank you very much for your answer. I don't know what algorithm uses openssl_public_encrypt.

I've tried this:

set json = "{""api_key"":""XXXXX"", ""id"":""1""}"
set file = ##class(%FileCharacterStream).%New()
set file.Filename = "public.key"
set key = file.Read(file.Size) 
set jsonEncrypt = $System.Encryption.RSAEncrypt(json, key)

But it doesn't work, it returns an empty string. I try to see the error using RSAGetLastError() and I don't get anything. The public.key has this format:

-----BEGIN PUBLIC KEY-----
......
......
......
......
-----END PUBLIC KEY-----

The line breaks are LF and it is in UTF-8. What format should the public key be in order to work in Ensemble? I am doing something wrong?

Sorry, I got the error with RSAGetLastError(). Is this:

error:0906D06C:PEM routines:PEM_read_bio:no start line;

I have checked that question, but I don't understand what happens.

Finally I have used this instruction "openssl rsautl -in fileIn.txt -out fileOut-enc.txt -pubin -inkey public.key -encrypt" using $ZF(-100) and having OpenSSL installed on the server and it works.

I want to do it with Encryption methods, there must be a way to do this with COS and not using shell instructions, right?

Sure. I think it's the key formatting error.

Can you try to bake the key into the class like this and use it instead of a file?

Here's an article on RSA encryption with InterSystems IRIS.