Assinando e verificando um envelope PIX (SPI)
// Importa o cliente Dinamo HSM import { hsm } from "@dinamonetworks/hsm-dinamo" ; // Define os parâmetros de conexão com o HSM const options = { host: "127.0.0.1" , authUsernamePassword: { username: "master" , password: "12345678" , }, }; // Chave privada RSA-2048 de teste (PKCS#1 DER) const testKey = Buffer . from ( "MIIEpAIBAAKCAQEA1/xVfpbP6NcY/VjVJ2q925ZpPRs2kVcMF/gJEIFmHeTwcN25LScM/y47Q0rUa7pvcXoMiDJPYS3zd7CPiJCS" + "WZ02T3lPG8XvlZJoFNXLWxMJIzW75d775d+Fq2s/y9BoPqdAuEMJa3Vg94tS6xKx/IlhZnQ2SWXsje8CNGeJcCYIjgaicU82FodJ" + "v6zei6olToLUbXOBYzWlZZ7L6WhvfPQ9f4ntTkvPf+4qZIuKxE0sM97EJvj5l8jJwf2hbl5DivKw2q9sWO+K2Wdoba/evTjIHKh5" + "W5/0S31zfIpB8V+TvDyLunGdIl+LZJpn3zpFzRm2LPAUFX2NSf79jIj7MQIDAQABAoIBAAj2tRYhPGzzg1sdVRBTGODMgd7aOqYm" + "xI7YmYi0tBgcxKFMhGdEMgEDqkw5Rm5XoREmsW80FlEISwzOODDA3kAHmyXKeS7kBLTSjA0ET/GeTUBnth38xnvEbmveMjo7Up46" + "CwCysIkECLORVc5Bev9J9M+/ljKu3xXHY/Iok17C88S6Ib8CeYkgf2wqry1+Hg0qJWyXR+m8PQtLdMjAtmwwfNthWy0U+oqQKbay" + "v1fLfgOkb5KVU28XgHSwLAH9/G7pN3gi8U4W4Hrp6jt9DN8LTZa3EzdjzyUhO+Dwowwg+2wZ9FhNPWmf96OYxaD30IOvz+rhqh0g" + "YKemr9QhoMECgYEA+mqqFyQTexnYfJRz/VxCFHm0OOkmMkFGGlXjT9mFPr3hkqxKcZo4n/l8gcSzrVOBD4j33K4CItKvpxQJMGLJ" + "yiP1AIx4PvEsDl+7HDFIeUmuIagV6CekDN9ONgzhW11iCFZZXIJCzPyf0t6j3QI2D5jTYHeaYulC5uuyKSDJCpECgYEA3M0ktXR8" + "JBCNGeLkIy7ugMlOOoB1f7KuWWWwcP6s2pA7bfPUVPFYdadkF0EZ8k7kxDEo7x49fNUU2TMOCTyePBFogT8hB2aL4479YcOASwGF" + "G6i2YxYrIFxBBzqk49LTaIqeTdH+ZAOYDAzuOgl7j191L5sjODjgp5DSvmPS9qECgYBh67HFSMMhYPLpjDdq/FeOoCScGHdqMWIT" + "TECN6dYTubZqX1rg31iDHdDVAbDs9vlBtOKPda+6JD6xi8EoHYkgtTzJ0SP4IOCEYmTNWmwnmWsxGAQw+sdIjU2NDy5URsjdz74z" + "0XADrklk8NCMzJ+NK8qEL2C8itAxcjsBoCNdMQKBgQCgr7J9U25cmKb3JcW9TRRJKTcDICVib1iuunBzawPEc56sX/wwbQthZBZV" + "Tg1h58RYeyY9DpbU2AU6JAuc8T5+nHSfSp/w0NIRIyiHE020SEDkZh2Fcsaj4D960VTab71moSqfm6k0g+ENNAPSvL/tER0pLg+t" + "hMcJaz3TTLZkwQKBgQCaT7jpE8E6YjWhlBbKH+7QaC4rj+6z4fvbY6cxBENrufFSt8lKm4gvU/vhrlCDkI0T55bS5HW3B4gtipLt" + "oIL0nBXHMqCU0zgyyI3pBmqUiqF8Kyn76MMMOJr0Qd07xLGs1CbWVVsGDeJbzunHpZ2uqbU3enHIM6wM1bv67/GrNQ=" , "base64" ); // Certificado de teste do assinante (X.509 DER) const testCert = Buffer . from ( "MIIDTzCCAjegAwIBAgIIAQAAAJgGhQAwDQYJKoZIhvcNAQELBQAwETEPMA0GA1UECwwGQ1NQQi0xMB4XDTI2MDMwMjIwMTUwOVoX" + "DTQ1MTExNzIwMTUwOVowejELMAkGA1UEBhMCQlIxEzARBgNVBAoMCklDUC1CcmFzaWwxFzAVBgNVBAsMDlNJU0JBQ0VOLTIzMjMy" + "MRYwFAYDVQQLDA1JU1BCLUEyM041NjdaMSUwIwYDVQQDDBxCYW5jbyBkZSBUZXN0ZXMgQWxmYW51bSBUMDAxMIIBIjANBgkqhkiG" + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1/xVfpbP6NcY/VjVJ2q925ZpPRs2kVcMF/gJEIFmHeTwcN25LScM/y47Q0rUa7pvcXoMiDJP" + "YS3zd7CPiJCSWZ02T3lPG8XvlZJoFNXLWxMJIzW75d775d+Fq2s/y9BoPqdAuEMJa3Vg94tS6xKx/IlhZnQ2SWXsje8CNGeJcCYI" + "jgaicU82FodJv6zei6olToLUbXOBYzWlZZ7L6WhvfPQ9f4ntTkvPf+4qZIuKxE0sM97EJvj5l8jJwf2hbl5DivKw2q9sWO+K2Wdo" + "ba/evTjIHKh5W5/0S31zfIpB8V+TvDyLunGdIl+LZJpn3zpFzRm2LPAUFX2NSf79jIj7MQIDAQABo0IwQDAdBgNVHQ4EFgQUgQsA" + "uG/CmEQ7Uremzv0sOf9XyIAwHwYDVR0jBBgwFoAUQzTsjBiE2IJ6r5CV/QH0RjYNWMQwDQYJKoZIhvcNAQELBQADggEBAKdB44D9" + "5Eq02RrqSw5jQJtK0ziJPFpGg3F/HVGjjo4TfMNZ3FRy+LCqiKbG5z/wokWMEgLgXZek9RaEq3Hg3KhoS/kmhgVFlU+z1WwzpIyP" + "6v1N2qkyKygBoIa6i8x5aNMeC8y7Q25t3/4boLvL/GtwGcnt9tCNMMaqiOyeoylB46HKeqRGHr4LrYBckHkL9NBfsJrLBrUepN+d" + "B/eRREtCqGPblruwgxlle1sEN6syWGe3B0zs29DDsM24mz+7l56uOZecceA4evYRzktgtNck+rOR/7esFxQ8a0ACN7vF0pQyiZeE" + "8XpDwVQO6/oEKjBZKzPe71wTWuC9YMP9+8A" , "base64" ); // Cadeia de certificados de teste (PKCS#7) const testChain = Buffer . from ( "MIIGbwYJKoZIhvcNAQcCoIIGYDCCBlwCAQExADALBgkqhkiG9w0BBwGgggZEMIIDTzCCAjegAwIBAgIIAQAAAJgGhQAwDQYJKoZI" + "hvcNAQELBQAwETEPMA0GA1UECwwGQ1NQQi0xMB4XDTI2MDMwMjIwMTUwOVoXDTQ1MTExNzIwMTUwOVowejELMAkGA1UEBhMCQlIx" + "EzARBgNVBAoMCklDUC1CcmFzaWwxFzAVBgNVBAsMDlNJU0JBQ0VOLTIzMjMyMRYwFAYDVQQLDA1JU1BCLUEyM041NjdaMSUwIwYD" + "VQQDDBxCYW5jbyBkZSBUZXN0ZXMgQWxmYW51bSBUMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1/xVfpbP6NcY" + "/VjVJ2q925ZpPRs2kVcMF/gJEIFmHeTwcN25LScM/y47Q0rUa7pvcXoMiDJPYS3zd7CPiJCSWZ02T3lPG8XvlZJoFNXLWxMJIzW7" + "5d775d+Fq2s/y9BoPqdAuEMJa3Vg94tS6xKx/IlhZnQ2SWXsje8CNGeJcCYIjgaicU82FodJv6zei6olToLUbXOBYzWlZZ7L6Whv" + "fPQ9f4ntTkvPf+4qZIuKxE0sM97EJvj5l8jJwf2hbl5DivKw2q9sWO+K2Wdoba/evTjIHKh5W5/0S31zfIpB8V+TvDyLunGdIl+L" + "ZJpn3zpFzRm2LPAUFX2NSf79jIj7MQIDAQABo0IwQDAdBgNVHQ4EFgQUgQsAuG/CmEQ7Uremzv0sOf9XyIAwHwYDVR0jBBgwFoAU" + "QzTsjBiE2IJ6r5CV/QH0RjYNWMQwDQYJKoZIhvcNAQELBQADggEBAKdB44D95Eq02RrqSw5jQJtK0ziJPFpGg3F/HVGjjo4TfMNZ" + "3FRy+LCqiKbG5z/wokWMEgLgXZek9RaEq3Hg3KhoS/kmhgVFlU+z1WwzpIyP6v1N2qkyKygBoIa6i8x5aNMeC8y7Q25t3/4boLvL" + "/GtwGcnt9tCNMMaqiOyeoylB46HKeqRGHr4LrYBckHkL9NBfsJrLBrUepN+dB/eRREtCqGPblruwgxlle1sEN6syWGe3B0zs29DD" + "sM24mz+7l56uOZecceA4evYRzktgtNck+rOR/7esFxQ8a0ACN7vF0pQyiZeE8XpDwVQO6/oEKjBZKzPe71wTWuC9YMP9+8AwggLt" + "MIIB1aADAgECAgEBMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAsMBkNTUEItMTAeFw0yMDAzMTIxOTE1MjVaFw0zNzAzMDgxOTE1" + "MjVaMBExDzANBgNVBAsMBkNTUEItMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0nA991POZeTzDc6OAdX/xjJLAw" + "fvIZ+LgsjLoGIYp1v7BMA5tKj56t6t2S03V+LkSRAnUoRTWzvGrtDmQdFm+06KfNfOOF5nFw06HWxafAqFHBjix5gW+CLDDmHFrY" + "2ctYkxnMQNcPLog6yzEjLOZ7Nycq1Hzgk+BAoFCmmuDHLuVaxFO85xqsMr69hnYe2iDM4Ee66d6NmscV5D9LomsD1dXjkMujElLM" + "evvOs3W1ryusv8Ypyy2Ss17f4HjIEOovSb7Vh5UV7P0gok0MiIwbvim5ucEU3nNAVabi/v2mcApaGBJDcMsbJ4EHttjyWVMpHxch" + "aBoPRjza3c8xfdsCAwEAAaNQME4wHQYDVR0OBBYEFEM07IwYhNiCeq+Qlf0B9EY2DVjEMB8GA1UdIwQYMBaAFEM07IwYhNiCeq+Q" + "lf0B9EY2DVjEMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHt2BYnx3ujecknLauEFDKsa5G/VX8KLlpzClQx1OpfN" + "IKIOvZ4kAO4rNJLZq7AJCeiX1UP4bu2TgDcCHeC74qbWRYDpHcE8nYTZdmq4WHUPlBjnViQrGCT0Si0qMogEi8qf9vVjtdb4yqkB" + "dOtIIunEugavQCVhZ5cVpQc1dPT/2Aw4YlNcSVXr2sdOpXNi8twWNdhkqnZFcovQGQZyhwcNk5GBofNGAn3kLibrvSFRodlIn691" + "HIhszuW/tnyNGCGKkli8OrKEEbI0pblp5NerVGEyPWcVksDbqN3Sfgj0yyi1DB2gWTP5a1CnvN7gF8lox1plADqxq+BK9QRuWZYx" + "AA=" , "base64" ); // Envelope PIX (pacs.008) não assinado const unsignedEnvelope = Buffer . from ( '<?xml version="1.0" encoding="UTF-8" standalone="no"?> \n ' + '<Envelope xmlns="https://www.bcb.gov.br/pacs.008.pix.1.1.xsd"> \n ' + " <AppHdr> \n " + " <Fr><FIId><FinInstnId><Othr><Id>00653405</Id></Othr></FinInstnId></FIId></Fr> \n " + " <To><FIId><FinInstnId><Othr><Id>00736634</Id></Othr></FinInstnId></FIId></To> \n " + " <BizMsgIdr>M00653405803f4a7e905e4355bf968a2</BizMsgIdr> \n " + " <MsgDefIdr>pacs.008.pix.1.1</MsgDefIdr> \n " + " <CreDt>2019-12-10T11:22:13.795Z</CreDt> \n " + " <Sgntr></Sgntr> \n " + " </AppHdr> \n " + " <Document> \n " + " <FIToFICstmrCdtTrf> \n " + " <GrpHdr> \n " + " <MsgId>M00653405803f4a7e905e4355bf968a2</MsgId> \n " + " <CreDtTm>2019-12-10T11:22:13.795Z</CreDtTm> \n " + " <NbOfTxs>1</NbOfTxs> \n " + " <SttlmInf><SttlmMtd>CLRG</SttlmMtd></SttlmInf> \n " + " <PmtTpInf><InstrPrty>HIGH</InstrPrty></PmtTpInf> \n " + " </GrpHdr> \n " + " </FIToFICstmrCdtTrf> \n " + " </Document> \n " + "</Envelope>" ); async function pixSignVerify () { // Conecta ao HSM const conn = await hsm . connect ( options ); const keyName = "pix_example_key" ; const certName = "pix_example_cert" ; const chainName = "pix_example_chain" ; // Remove objetos de execuções anteriores, se existirem for ( const name of [ keyName , certName , chainName ]) { try { await conn . key . delete ( name ); } catch { // Objeto não existe } } // Importa a chave privada, o certificado do assinante e a cadeia de confiança await conn . key . import ( keyName , hsm . enums . RSA_ASYMMETRIC_KEYS . ALG_RSA_2048 , testKey , true ); await conn . key . importCertificate ( certName , testCert ); await conn . key . importCertificate ( chainName , testChain ); console . log ( "Chave e certificados importados" ); // Assina o envelope PIX (a assinatura XMLDSig é inserida no elemento Sgntr) const signedEnvelope = await conn . pix . PIXSign ( 0 , // Flags de assinatura (veja hsm.enums.PIX_SIGN_FLAGS) keyName , // Nome da chave privada certName , // Nome do certificado do assinante unsignedEnvelope // Envelope PIX não assinado ); console . log ( "Envelope PIX assinado com sucesso" ); // Verifica a assinatura do envelope usando a cadeia de confiança await conn . pix . PIXVerify ( chainName , // Nome da cadeia de certificados (âncora de confiança) null , // CRL (opcional) 0 , // Flags de verificação signedEnvelope // Envelope PIX assinado ); console . log ( "Assinatura do envelope PIX verificada com sucesso" ); // Remove os objetos criados for ( const name of [ keyName , certName , chainName ]) { await conn . key . delete ( name ); } // Desconecta do HSM await conn . disconnect (); } // Executa a função pixSignVerify pixSignVerify ();
Copy