Solapas principales

Pregunta
Laura Blázquez ... · Feb 19, 2020

openssl_public_encrypt para Ensemble

Hola.

Necesitamos llamar a un servicio y tenemos que encriptar la petición utilizando una clave pública. Tenemos un ejemplo de cómo realizar la llamada en PHP. También tenemos la clave pública y todos los parámetros que necesitamos. El ejemplo en PHP es éste y funciona (utiliza 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);

Necesitamos hacer lo mismo en Ensemble. Escribí un post en la comunidad de InterSystems en inglés, y me dijeron que utilizase RSAEncrypt().

He probado esto:

set json = "{""api_key"":""XXXXX"", ""id"":""1""}"

// Abrir el fichero de la clave pública:
set file = ##class(%FileCharacterStream).%New()
set file.Filename = "public.key"
set key = file.Read(file.Size)

// Encriptar el JSON
set jsonEncrypt = $System.Encryption.RSAEncrypt(json, key)

Pero no funciona, me devuelve un string vacío. He buscado por todas partes y no sé por qué no funciona. La clave pública tiene este formato:

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

Los saltos de línea son LF y está en UTF-8. En qué formato debe estar la clave pública para que funcione en Ensemble? Estoy haciendo algo mal?

Muchas gracias de antemano.

00
0 5 82 1

Respuestas

Perdón, he conseguido obtener el error con RSAGetLastError(), y me devuelve esto:

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

Hola Laura, tendría que mirar como usar esa función, pero una cosa que siempre puedes hacer ya que te funciona en openSSL es llamar directamente a OpenSSL. Échale un ojo a este ejemplo https://github.com/drechema/ensemble-smime

Gracias David.

Al final, dado que el comando de terminal funcionaba, esto es exactamente lo que hice, invocar el comando utilizando $ZF(-100, "openssl", ...). Con esto hemos conseguido que funcione. Entiendo que es una solución igualmente válida, no? Me hubiera gustado poder realizarlo con los métodos de clase de $System.Encryption, pero no lo he conseguido.

He mirado este artículo y estoy invocando correctamente el método. Lo que sí he tenido que hacer es reconvertir la clave pública de pkcs#8 a pkcs#1 como indica en el artículo. Con eso consigo que encripte, aunque luego el sistema del proveedor me dice que no es válido, pero quizá sea que me falte/sobre algo. Seguiré probando a ver si consigo hacerlo funcionar.

Muchas gracias!