Firmas RSA
Todas las operaciones con STP se autentican mediante firmas digitales RSA-SHA256. Las claves se almacenan en AWS Secrets Manager, nunca en el código.
Algoritmo
Sección titulada «Algoritmo»- Firma (outgoing):
crypto.createSign('RSA-SHA256')con clave privada en formato PEM codificada en Base64 - Verificación (incoming):
crypto.createVerify('SHA256')con clave pública de STP en Base64 - Formato de salida: Base64
Clases disponibles (lib/cryptoHandler.js)
Sección titulada «Clases disponibles (lib/cryptoHandler.js)»Cada tipo de operación tiene su propia clase que construye la cadena original correcta:
| Clase | Uso |
|---|---|
CryptoHandlerOrdenPago | Orden de pago SPEI saliente |
CryptoHandlerCuenta | Registro de cuenta en STP |
CryptoHandlerAbono | Verificar abono entrante de STP |
CryptoHandlerSaldoCuenta | Consulta de saldo |
CryptoHandlerConciliacion | Consulta de conciliación |
CryptoHandlerNotificacionEstadoCuenta | Verificar notificación de cuenta |
CryptoHandlerNotificacionEstadoTransaccion | Verificar notificación de transacción |
Cadenas originales
Sección titulada «Cadenas originales»Las cadenas originales usan el separador | y siempre empiezan y terminan con ||.
Orden de pago (CryptoHandlerOrdenPago)
Sección titulada «Orden de pago (CryptoHandlerOrdenPago)»||{institucionContraparte}|{empresa}|||{claveRastreo}|{institucionOperante}|{monto}|{tipoPago}|{tipoCuentaOrdenante}|{nombreOrdenante}|{cuentaOrdenante}|{rfcCurpOrdenante}|{tipoCuentaBeneficiario}|{nombreBeneficiario}|{cuentaBeneficiario}|{rfcCurpBeneficiario}||||||{conceptoPago}|||||||{referenciaNumerica}|||||||{nombreParticipanteIndirecto}|{cuentaParticipanteIndirecto}|{rfcParticipanteIndirecto}||Registro de cuenta (CryptoHandlerCuenta)
Sección titulada «Registro de cuenta (CryptoHandlerCuenta)»||{empresa}|{cuenta}|{rfcCurp}||Abono entrante (CryptoHandlerAbono)
Sección titulada «Abono entrante (CryptoHandlerAbono)»||{id}|{fechaOperacion}|{institucionOrdenante}|{institucionBeneficiaria}|{claveRastreo}|{monto}|{nombreOrdenante}|{tipoCuentaOrdenante}|{cuentaOrdenante}|{rfcCurpOrdenante}|{nombreBeneficiario}|{tipoCuentaBeneficiario}|{cuentaBeneficiario}|{nombreBeneficiario2}|{tipoCuentaBeneficiario2}|{cuentaBeneficiario2}|{rfcCurpBeneficiario}|{conceptoPago}|{referenciaNumerica}|{empresa}|{tipoPago}|{tsLiquidacion}|{folioCodi}||Saldo de cuenta (CryptoHandlerSaldoCuenta)
Sección titulada «Saldo de cuenta (CryptoHandlerSaldoCuenta)»||{empresa}|{cuentaOrdenante}|{fecha}||Conciliación (CryptoHandlerConciliacion)
Sección titulada «Conciliación (CryptoHandlerConciliacion)»||{empresa}|{tipoOrden}|{fechaOperacion}||Notificación estado de cuenta (CryptoHandlerNotificacionEstadoCuenta)
Sección titulada «Notificación estado de cuenta (CryptoHandlerNotificacionEstadoCuenta)»||{cuenta}|{empresa}|{estado}|{observaciones}||Notificación estado de transacción (CryptoHandlerNotificacionEstadoTransaccion)
Sección titulada «Notificación estado de transacción (CryptoHandlerNotificacionEstadoTransaccion)»||{id}|{empresa}|{folioOrigen}|{estado}|{causaDevolucion}|{tsLiquidacion}||Uso en código
Sección titulada «Uso en código»Firmar una operación (outgoing)
Sección titulada «Firmar una operación (outgoing)»const CryptoHandler = require('./lib/cryptoHandler');
// Construir la clase con los datos de la operaciónconst crypto = new CryptoHandler.CryptoHandlerCuenta({ empresa: 'FINALITIX', cuenta: '64618001000001237', rfcCurp: 'PEGJ800101ABC'});
// Obtener la firma en Base64const firma = crypto.getSign( bankSecretData.secret.passphrase, bankSecretData.secret.privateKey // PEM en Base64);
// Incluir en el body de la petición a STPaccountData.firma = firma;Verificar firma entrante (incoming desde STP)
Sección titulada «Verificar firma entrante (incoming desde STP)»// Solo se ejecuta en ENV === 'prod'if (process.env.ENV === 'prod') { const { firma } = body; delete body.firma; // La firma NO se incluye en la cadena original
const crypto = new CryptoHandler.CryptoHandlerAbono(body); const valid = crypto.verify(firma, bankSecretData.secret.publicKey); // PEM en Base64
if (!valid) { return { status: 500, message: 'error validando firma' }; }}Almacenamiento de claves
Sección titulada «Almacenamiento de claves»Las claves se obtienen de AWS Secrets Manager en cada sesión y se cachean en memoria:
const bankSecretData = await Helper.retrieveSecret(null, process.env.STP_SECRET_NAME);
// Estructura del secreto{ "privateKey": "<PEM privado codificado en Base64>", "publicKey": "<PEM público de STP codificado en Base64>", "passphrase": "<passphrase de la clave privada>"}