From c08629337c9ea26512f7e6b34f4e781eb454dea7 Mon Sep 17 00:00:00 2001 From: bit4bit Date: Mon, 20 Dec 2021 01:38:13 +0000 Subject: [PATCH] facho-signer: se separa main de libreria facho-signer FossilOrigin-Name: ccb333de3a3210a4e82fb102e3eb41cb2d26c8fea5dd153898728978f85539b0 --- experimental/facho-signer/src/Makefile.am | 2 +- experimental/facho-signer/src/facho_signer.c | 165 +++++++------------ experimental/facho-signer/src/facho_signer.h | 15 ++ experimental/facho-signer/src/main.c | 32 ++++ 4 files changed, 110 insertions(+), 104 deletions(-) create mode 100644 experimental/facho-signer/src/facho_signer.h create mode 100644 experimental/facho-signer/src/main.c diff --git a/experimental/facho-signer/src/Makefile.am b/experimental/facho-signer/src/Makefile.am index 42357a3..ed4429b 100644 --- a/experimental/facho-signer/src/Makefile.am +++ b/experimental/facho-signer/src/Makefile.am @@ -1,4 +1,4 @@ bin_PROGRAMS = facho_signer -facho_signer_SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c +facho_signer_SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c main.c facho_signer_CFLAGS = $(OPENSSL_CFLAGS) $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING facho_signer_LDADD = $(OPENSSL_LIBS) $(LIBLTDL) $(XMLSEC1_LIBS) diff --git a/experimental/facho-signer/src/facho_signer.c b/experimental/facho-signer/src/facho_signer.c index ce063bd..9693dd0 100644 --- a/experimental/facho-signer/src/facho_signer.c +++ b/experimental/facho-signer/src/facho_signer.c @@ -10,27 +10,24 @@ #include #include - -#define print_error(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) -#define print_info(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) +#define xmlFachoPrintError(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) +#define xmlFachoPrintInfo(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) const xmlChar ublExtensionDSigNs[] = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"; const xmlChar policyIdDescription[] = "Política de firma para facturas electrónicas de la República de Colombia."; const xmlChar policyIdIdentifier[] = "https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf"; -char *basename = NULL; - // crea elemento /Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent -xmlNodePtr +static xmlNodePtr xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc); // FeC requiere que el digest value del policy identifier sea // apartir del contenido de la url. -int +static int xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *, xmlSecBufferPtr); -int +static int xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { xmlNodePtr qualifyingPropertiesNode = NULL; xmlNodePtr signedPropertiesNode = NULL; @@ -47,13 +44,13 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { qualifyingPropertiesNode = xmlXadesTmplQualifyingPropertiesCreate(doc, signNode, BAD_CAST "xades-ref1"); if ( qualifyingPropertiesNode == NULL ) { - print_error("error: failed to add QualifyingProperties node.\n"); + xmlFachoPrintError("error: failed to add QualifyingProperties node.\n"); goto fail; } signedPropertiesNode = xmlXadesTmplAddSignedProperties(qualifyingPropertiesNode, signedPropertiesId); if ( signedPropertiesNode == NULL ) { - print_error("error: xades failed to add signed properties node.\n"); + xmlFachoPrintError("error: xades failed to add signed properties node.\n"); goto fail; } @@ -63,54 +60,54 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { signedPropertiesRef, BAD_CAST "http://uri.etsi.org/01903#SignedProperties"); if ( refNode == NULL ) { - print_error("error: failed to add reference to signature template xades.\n"); + xmlFachoPrintError("error: failed to add reference to signature template xades.\n"); goto fail; } if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformInclC14NId) == NULL ) { - print_error("error: failed to add enveloped transform to reference for xades\n"); + xmlFachoPrintError("error: failed to add enveloped transform to reference for xades\n"); goto fail; } const time_t now = time(NULL); signedSignaturePropertiesNode = xmlXadesTmplAddSignedSignatureProperties(signedPropertiesNode, localtime(&now)); if ( signedSignaturePropertiesNode == NULL ) { - print_error("error: xades failed to add signed signature properties node.\n"); + xmlFachoPrintError("error: xades failed to add signed signature properties node.\n"); goto fail; } signingCertificateNode = xmlXadesTmplAddSigningCertificate(signedSignaturePropertiesNode, xmlSecTransformSha256Id); if ( signingCertificateNode == NULL ) { - print_error("error: failed to add SigningCertificate node \n"); + xmlFachoPrintError("error: failed to add SigningCertificate node \n"); goto fail; } signaturePolicyIdentifierNode = xmlXadesTmplAddSignaturePolicyIdentifier(signedSignaturePropertiesNode); if ( signaturePolicyIdentifierNode == NULL ) { - print_error("error: failed to add PolicyIdentifier node\n"); + xmlFachoPrintError("error: failed to add PolicyIdentifier node\n"); goto fail; } signaturePolicyIdNode = xmlXadesTmplAddSignaturePolicyId(signaturePolicyIdentifierNode); if ( signaturePolicyIdNode == NULL ) { - print_error("error: failed to add SignaturePolicyId node.\n"); + xmlFachoPrintError("error: failed to add SignaturePolicyId node.\n"); goto fail; } sigPolicyIdNode = xmlXadesTmplAddSigPolicyId(signaturePolicyIdNode, policyIdIdentifier, policyIdDescription); if ( sigPolicyIdNode == NULL ) { - print_error("error: failed to add SigPolicyId node.\n"); + xmlFachoPrintError("error: failed to add SigPolicyId node.\n"); goto fail; } sigPolicyHashNode = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode, xmlSecTransformSha256Id); if ( sigPolicyHashNode == NULL ) { - print_error("error: failed to add SigPolicyHash node.\n"); + xmlFachoPrintError("error: failed to add SigPolicyHash node.\n"); goto fail; } signerRoleNode = xmlXadesTmplAddSignerRole(signedSignaturePropertiesNode, BAD_CAST "supplier"); if ( signerRoleNode == NULL ) { - print_error("error: failed to add SignerRole node.\n"); + xmlFachoPrintError("error: failed to add SignerRole node.\n"); goto fail; } @@ -122,18 +119,18 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { return(-1); } -static int -xmlXadesAppInit() { +int +xmlFachoInit() { xmlInitParser(); LIBXML_TEST_VERSION; if ( xmlSecInit() < 0 ) { - print_error("xmlsec initialization failed.\n"); + xmlFachoPrintError("xmlsec initialization failed.\n"); return(-1); } if ( xmlSecCheckVersion() != 1 ) { - print_error("loaded xmlsec library version is not compatible.\n"); + xmlFachoPrintError("loaded xmlsec library version is not compatible.\n"); return(-1); } @@ -147,61 +144,39 @@ xmlXadesAppInit() { #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ if ( xmlSecCryptoAppInit(NULL) < 0 ) { - print_error("crypto initialization failed.\n"); + xmlFachoPrintError("crypto initialization failed.\n"); return(-1); } if ( xmlSecCryptoInit() < 0 ) { - print_error("xmlsec-crypto initialization failed.\n"); + xmlFachoPrintError("xmlsec-crypto initialization failed.\n"); return(-1); } return(0); } -static int -xmlXadesAppShutdown() { +int +xmlFachoShutdown() { if ( xmlSecCryptoShutdown() < 0 ) { - print_error("xmlSecCryptoShutdown failed.\n"); + xmlFachoPrintError("xmlSecCryptoShutdown failed.\n"); } if ( xmlSecCryptoAppShutdown() < 0 ) { - print_error("xmlSecCryptoAppShutdown failed.\n"); + xmlFachoPrintError("xmlSecCryptoAppShutdown failed.\n"); } if ( xmlSecShutdown() < 0 ) { - print_error("xmlsec shutdown failed.\n"); + xmlFachoPrintError("xmlsec shutdown failed.\n"); } xmlCleanupParser(); return(0); } -/* - X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyData, 0); - if (cert == NULL) { - print_error("xmlSecOpenSSLKeyDataX509GetKeyCert fail\n"); - } - - char *issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); - - printf("x509 issuer: %s\n", issuer); - - //https://stackoverflow.com/questions/9749560/how-to-calculate-x-509-certificates-sha-1-fingerprint-in-c-c-objective-c - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int n; - const EVP_MD *digest = EVP_get_digestbyname("sha256"); - X509_digest(cert, digest, md, &n); - printf("%s", "Fingerprint:"); - for(int pos = 0; pos < 19 ; pos++) { - printf("%02x:", md[pos]); - } - printf("%02x\n", md[19]); -*/ - -static int -xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *password) { +int +xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password) { xmlDocPtr doc = NULL; xmlNodePtr signNode = NULL; xmlNodePtr refNode = NULL; @@ -219,14 +194,14 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw doc = xmlParseFile(filename); if ( (doc == NULL) || (xmlDocGetRootElement(doc) == NULL) ) { - print_error("error: unable to parse file %s\n", filename); + xmlFachoPrintError("error: unable to parse file %s\n", filename); goto done; } signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14NId, xmlSecTransformRsaSha256Id, NULL); if ( signNode == NULL ) { - print_error("error: failed to create signature template.\n"); + xmlFachoPrintError("error: failed to create signature template.\n"); goto done; } @@ -238,11 +213,11 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw BAD_CAST "", //uri NULL); //type if ( refNode == NULL ) { - print_error("error: failed to add reference to signature template.\n"); + xmlFachoPrintError("error: failed to add reference to signature template.\n"); goto done; } if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL ) { - print_error("error: failed to add enveloped transform to reference\n"); + xmlFachoPrintError("error: failed to add enveloped transform to reference\n"); goto done; } @@ -252,72 +227,79 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw BAD_CAST "#xmldsig-facho-KeyInfo", NULL); if ( refNode == NULL ) { - print_error("error: failed to add reference to signature template key-info.\n"); + xmlFachoPrintError("error: failed to add reference to signature template key-info.\n"); goto done; } keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, BAD_CAST "xmldsig-facho-KeyInfo"); if ( keyInfoNode == NULL ) { - print_error("error: failed to add key info.\n"); + xmlFachoPrintError("error: failed to add key info.\n"); goto done; } x509DataNode = xmlSecTmplKeyInfoAddX509Data(keyInfoNode); if ( x509DataNode == NULL ) { - print_error("error: failde to add x509 DATA \n"); + xmlFachoPrintError("error: failde to add x509 DATA \n"); goto done; } if ( xmlSecTmplX509DataAddCertificate(x509DataNode) == NULL ) { - print_error("error: failde to add x509Certificate node\n"); + xmlFachoPrintError("error: failde to add x509Certificate node\n"); goto done; } if ( xmlFachoTmplXadesCreate(doc, signNode) < 0 ){ - print_error("error: xmlFachoTmplXadesCreate failed.\n"); + xmlFachoPrintError("error: xmlFachoTmplXadesCreate failed.\n"); goto done; } dsigCtx = xmlSecDSigCtxCreate(NULL); if ( dsigCtx == NULL ) { - print_error("error: dsig context creating failed\n"); + xmlFachoPrintError("error: dsig context creating failed\n"); return(-1); } - + + // cargamos el archivo pkcs12 con llave privado y certificados x509 dsigCtx->signKey = xmlSecCryptoAppKeyLoad(pkcs12name, xmlSecKeyDataFormatPkcs12, password, NULL, NULL); if ( dsigCtx->signKey == NULL ) { - print_error("error: failed to load pkcs12\n"); + xmlFachoPrintError("error: failed to load pkcs12\n"); goto done; } xmlXadesPolicyIdentifierCtx policyIdCtx; + // por ahora el hash del identificador lo tomamos del pdf de la dian policyIdCtx.contentCallback = &xmlFachoPolicyIdentifierCtxFromFilename; xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx, XADES_DIGEST_SHA256, &policyIdCtx); if ( xadesDsigCtx == NULL ) { - print_error("error: xades context creating failed.\n"); + xmlFachoPrintError("error: xades context creating failed.\n"); return(-1); } - if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) { - print_error("error: signature failed\n"); + // debe existir el elemento antes del firmado + node = xmlFachoTmplUBLExtensionAddExtensionContent(doc); + if ( node == NULL ) { + xmlFachoPrintError("error: failed to add UBLExtensions/UBLExtension/ExtensionContent\n"); goto done; } - node = xmlFachoTmplUBLExtensionAddExtensionContent(doc); - if ( node == NULL ) { - print_error("error: failed to add UBLExtensions/UBLExtension/ExtensionContent\n"); + + // realizar firma de documento + if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) { + xmlFachoPrintError("error: signature failed\n"); goto done; } + + xmlUnlinkNode(signNode); xmlSecAddChildNode(node, signNode); - xmlDocDump(stdout, doc); + xmlDocDump(out, doc); res = 0; @@ -336,32 +318,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw return(res); } -int main(int argc, char *argv[]) { - basename = argv[0]; - int exitStatus = EXIT_SUCCESS; - - if (argc != 4) { - print_error("%s: \n", basename); - return(EXIT_FAILURE); - } - - if ( xmlXadesAppInit() < 0 ) { - print_error("initialization failed.\n"); - return(EXIT_FAILURE); - } - - if ( xmlXadesSignFile( argv[1], argv[2], argv[3] ) != 0 ) { - print_error("%s", "fail to sign file\n"); - exitStatus = EXIT_FAILURE; - } - - xmlXadesAppShutdown(); - return(exitStatus); -} - - - -xmlNodePtr +static xmlNodePtr xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) { xmlNodePtr node = NULL; xmlNodePtr parent = NULL; @@ -373,28 +330,30 @@ xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) { if ( parent == NULL ) { parent = xmlSecAddChild(xmlDocGetRootElement(doc), ublExtensionsName, ublExtensionDSigNs); if ( parent == NULL ) { - print_error("error: failed to cleate UBLExtensions.\n"); + xmlFachoPrintError("error: failed to cleate UBLExtensions.\n"); return(NULL); } } + // adicionamos nuevo elemento UBLExtension node = xmlSecAddChild(parent, ublExtensionName, ublExtensionDSigNs); if ( node == NULL ) { - print_error("error: failed to add UBLExtension\n"); + xmlFachoPrintError("error: failed to add UBLExtension\n"); xmlFreeNode(parent); return(NULL); } + // adicionamos nuevo elemento ExtensionContent node = xmlSecAddChild(node, extensionContentName, ublExtensionDSigNs); if ( node == NULL ) { - print_error("error: failed to add ExtensionContent"); + xmlFachoPrintError("error: failed to add ExtensionContent"); return(NULL); } return(node); } -int +static int xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *policyId, xmlSecBufferPtr buffer) { static unsigned char politicafirmav2[] = { /** diff --git a/experimental/facho-signer/src/facho_signer.h b/experimental/facho-signer/src/facho_signer.h new file mode 100644 index 0000000..81858da --- /dev/null +++ b/experimental/facho-signer/src/facho_signer.h @@ -0,0 +1,15 @@ +#ifndef FACHO_SIGNER_H +#define FACHO_SIGNER_H + +#include + +int +xmlFachoInit(); + +int +xmlFachoShutdown(); + +int +xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password); + +#endif /* FACHO_SIGNER_H */ diff --git a/experimental/facho-signer/src/main.c b/experimental/facho-signer/src/main.c new file mode 100644 index 0000000..30d2fa9 --- /dev/null +++ b/experimental/facho-signer/src/main.c @@ -0,0 +1,32 @@ +#include "xades/xades.h" +#include "facho_signer.h" + +#include +#include + + +static char *basename = NULL; + +int main(int argc, char *argv[]) { + int exitStatus = EXIT_SUCCESS; + + basename = argv[0]; + + if (argc != 4) { + fprintf(stderr, "%s: \n", basename); + return(EXIT_FAILURE); + } + + if ( xmlFachoInit() < 0 ) { + fprintf(stderr, "initialization failed.\n"); + return(EXIT_FAILURE); + } + + if ( xmlFachoSignFile( stdout, argv[1], argv[2], argv[3] ) != 0 ) { + fprintf(stderr, "fail to sign file\n"); + exitStatus = EXIT_FAILURE; + } + + xmlFachoShutdown(); + return(exitStatus); +}