Autorización

Para garantizar la máxima seguridad e integridad en operaciones críticas, Duemint requiere que estas solicitudes sean autorizadas mediante una firma digital. Piensa en esta firma como un sello notarial digital: comprueba que la solicitud fue creada por ti (autenticidad), que no fue alterada en el camino (integridad).

Este proceso se basa en un par de llaves criptográficas RSA de 2048 bits que tú administras. Tú guardas la llave privada para firmar y registras tu llave pública en Duemint para que podamos verificar la firma.

Para firmar la operación, se debe utilizar el algoritmo PS256 de JWA que usa RSA, utilizar la llave privada y enviar el certificado con la llave pública. El certificado DER encodeado en base64 debe ir incluido en encabezado x5c en formato PEM. En la práctica, el body de la solicitud en formato JSON se firma para comprobar en el destinatario que la solicitud no fue alterada.

Operaciones que requieren autorización

No todas las transacciones requieren autorización para ejecutarse. omite esta sección si no quieres realizar alguna de las siguientes operaciones.

  • Pagos desde la billetera a otras cuentas

Genera las llaves

Primero tienes que generar tu clave publico privada, la publica vas a tener que guardarla en el sistema de duemint y la privada la vas a usar para encriptar tus llamadas firmadas.

Guarda el archivo privateKey.pem en un lugar extremadamente seguro. Este archivo es tu secreto para firmar transacciones.

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.pem -out publicKey.pem

Carga la llave publica

  1. Convierte tu llave pública a formato DER
    Usa el siguiente código para convertir el archivo publicKey.pem generado anteriormente:
import { X509Certificate } from 'crypto';
import { readFileSync } from 'fs';

// Leer la llave pública PEM
const certificate = readFileSync('./certs/publicKey.pem', 'utf-8');

// Convertir a formato DER (base64)
const x509 = new X509Certificate(certificate);
const derCertificate = x509.raw.toString('base64');

  1. Sube el certificado en el Dashboard de Duemint
    Ingresa a la configuración y navega a:
    Usuarios → Usuarios API → (Selecciona el usuario API) → Llave pública → Cargar llave pública
  2. Firma la llave pública
    Una vez cargada, firma la llave para completar la autorización. Luego podrás continuar con el siguiente paso del proceso.

Proceso de firma

Para firmar una operación, se usa el algoritmo PS256 (RSA) definido en JWA.
Debes firmar el cuerpo de la solicitud (en formato JSON) con tu llave privada y adjuntar el certificado que contiene tu llave pública en el encabezado x5c, codificado en base64 (DER).

Esto permite que el receptor verifique que la solicitud proviene del usuario API correcto y que no fue modificada.

Nota: La firma solo es válida para solicitudes realizadas con un token de usuario API vinculado a la llave pública utilizada.

Ejemplo en Node.js:

import { X509Certificate } from 'crypto';
import { FlattenedSign, importPKCS8 } from 'jose';
import { readFileSync } from 'fs';
import { Buffer } from 'buffer';

// Leer las llaves privada y pública desde los archivos PEM
const privateKey = readFileSync('./certs/privateKey.pem', 'utf-8');
const certificate = readFileSync('./certs/publicKey.pem', 'utf-8');

// Convertir el certificado público a formato DER (base64)
const x509 = new X509Certificate(certificate);
const derCertificate = x509.raw.toString('base64');

// Documento que se desea firmar
const document = '{description:"body example"}';

// Importar la llave privada en formato PKCS8 usando el algoritmo PS256
const ecPrivateKey = await importPKCS8(privateKey, 'PS256');

// Convertir el documento a bytes
const payload = Buffer.from(document, 'utf-8');

// Firmar el documento usando JWS en formato "Flattened"
const jws = await new FlattenedSign(new Uint8Array(payload))
  .setProtectedHeader({
    alg: 'PS256',          // Algoritmo de firma
    b64: false,            // Indica que el payload no está en base64
    crit: ['b64'],         // Define 'b64' como campo crítico
    x5c: [derCertificate], // Incluye el certificado en formato DER
  })
  .sign(ecPrivateKey);

// Construir el header de firma en formato esperado por Duemint
const duemintSignatureHeader = `${jws.protected}..${jws.signature}`;

La firma obtenida se debe incluir en el header de la solicitud en “duemint-signature”.

Firma tu request

La firma permite identificar que la solicitud fue emitida por un emisor autorizado para realizar operaciones sensibles que requieren firma del apoderado de la empresa. Esta debe ser incluida en la cabecera de la solicitud, como se muestra a continuación;

const options = {
    headers: {
        ...
        "duemint-signature": "<signature>", 
    }
};