facho-signer: se adiciona SigPolicyId
FossilOrigin-Name: c27a531da0a2dbca77e3c0b944735a4fc4266142e505b310d4ca8cf1f3d11596
This commit is contained in:
parent
a320b5a7b0
commit
012615f984
@ -14,6 +14,8 @@
|
||||
#define print_info(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;
|
||||
|
||||
@ -21,6 +23,12 @@ char *basename = NULL;
|
||||
xmlNodePtr
|
||||
xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc);
|
||||
|
||||
// FeC requiere que el digest value del policy identifier sea
|
||||
// apartir del contenido de la url.
|
||||
xmlXadesPolicyIdentifierCtxPtr
|
||||
xmlFachoPolicyIdentifierCtxFromFilename(const char *filename);
|
||||
|
||||
|
||||
int
|
||||
xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
|
||||
xmlNodePtr qualifyingPropertiesNode = NULL;
|
||||
@ -28,6 +36,9 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
|
||||
xmlNodePtr signedSignaturePropertiesNode = NULL;
|
||||
xmlNodePtr signingCertificateNode = NULL;
|
||||
xmlNodePtr signaturePolicyIdentifierNode = NULL;
|
||||
xmlNodePtr signaturePolicyIdNode = NULL;
|
||||
xmlNodePtr sigPolicyIdNode = NULL;
|
||||
xmlNodePtr sigPolicyHashNode = NULL;
|
||||
xmlNodePtr signerRoleNode = NULL;
|
||||
xmlNodePtr refNode = NULL;
|
||||
const xmlChar signedPropertiesId[] = "xmldsig-facho-signed-props";
|
||||
@ -78,12 +89,31 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
signaturePolicyIdNode = xmlXadesTmplAddSignaturePolicyId(signaturePolicyIdentifierNode);
|
||||
if ( signaturePolicyIdNode == NULL ) {
|
||||
print_error("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");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sigPolicyHashNode = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode, xmlSecTransformSha256Id);
|
||||
if ( sigPolicyHashNode == NULL ) {
|
||||
print_error("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");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
return(0);
|
||||
fail:
|
||||
xmlUnlinkNode(qualifyingPropertiesNode);
|
||||
@ -217,7 +247,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
|
||||
|
||||
refNode = xmlSecTmplSignatureAddReference(signNode,
|
||||
xmlSecTransformSha256Id,
|
||||
BAD_CAST "xmldsig-facho-ref1",
|
||||
BAD_CAST "xmldsig-facho-ref2",
|
||||
BAD_CAST "#xmldsig-facho-KeyInfo",
|
||||
NULL);
|
||||
if ( refNode == NULL ) {
|
||||
@ -263,7 +293,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw
|
||||
goto done;
|
||||
}
|
||||
|
||||
xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx);
|
||||
xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx, XADES_DIGEST_SHA256, NULL);
|
||||
if ( xadesDsigCtx == NULL ) {
|
||||
print_error("error: xades context creating failed.\n");
|
||||
return(-1);
|
||||
@ -358,3 +388,8 @@ xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) {
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
xmlXadesPolicyIdentifierCtxPtr
|
||||
xmlFachoPolicyIdentifierCtxFromFilename(const char *filename) {
|
||||
return(NULL);
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode) {
|
||||
|
||||
cur = xmlSecAddChild(signaturePolicyIdentifierNode, xmlXadesNodeSignaturePolicyId, xmlXadesDSigNs);
|
||||
if (cur == NULL) {
|
||||
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSignaturePolicyId)", NULL);
|
||||
xmlXadesInternalError("xmlsecAddChild(cur)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@ xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode) {
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description, xmlSecTransformId policyDigestMethodId) {
|
||||
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description) {
|
||||
xmlNodePtr sigPolicyIdNode;
|
||||
xmlNodePtr node;
|
||||
int ret;
|
||||
@ -276,7 +276,7 @@ xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifi
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret = xmlSecNodeEncodeAndSetContent(node, identifier);
|
||||
ret = xmlSecNodeEncodeAndSetContent(node, description);
|
||||
if (ret < 0) {
|
||||
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||
xmlFreeNode(sigPolicyIdNode);
|
||||
@ -288,7 +288,7 @@ xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifi
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode) {
|
||||
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId) {
|
||||
xmlNodePtr node;
|
||||
xmlXadesAssert2(parentNode != NULL, NULL);
|
||||
|
||||
@ -299,6 +299,11 @@ xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if ( xmlXadesTmplAddDigest(node, digestMethodId->href, BAD_CAST "") == NULL) {
|
||||
xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -12,48 +12,10 @@
|
||||
#include <ctype.h>
|
||||
|
||||
static xmlNodePtr
|
||||
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath) {
|
||||
xmlXPathContextPtr xpathCtx;
|
||||
xmlXPathObjectPtr xpathResult;
|
||||
xmlNodePtr node;
|
||||
|
||||
// obtener QualifyingProteries
|
||||
|
||||
xpathCtx = xmlXPathNewContext(doc);
|
||||
/* register namespaces */
|
||||
// TOMADO DE: xmlsec1/src/xpath.c
|
||||
for(xmlNsPtr ns = xmlDocGetRootElement(doc)->nsDef; ns != NULL; ns = ns->next) {
|
||||
/* check that we have no other namespace with same prefix already */
|
||||
if((ns->prefix != NULL) && (xmlXPathNsLookup(xpathCtx, ns->prefix) == NULL)){
|
||||
int ret = xmlXPathRegisterNs(xpathCtx, ns->prefix, ns->href);
|
||||
if(ret != 0) {
|
||||
xmlXadesXmlError2("xmlXPathRegisterNs", NULL,
|
||||
"prefix=%s", xmlSecErrorsSafeString(ns->prefix));
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xpathResult = xmlXPathEvalExpression(BAD_CAST "//ds:Object/xades:QualifyingProperties[1]", xpathCtx);
|
||||
if ( xmlXPathNodeSetIsEmpty( xpathResult->nodesetval ) ) {
|
||||
xmlXadesInternalError("can't find ds:Signature/ds:Object/xades:QualifyingProperties \n", NULL);
|
||||
xmlXPathFreeObject(xpathResult);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// obtener puntero a nodo
|
||||
node = xpathResult->nodesetval->nodeTab[0];
|
||||
if ( node->type != XML_ELEMENT_NODE ) {
|
||||
xmlXadesInternalError("expected element QualifyingProperties\n", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath);
|
||||
|
||||
xmlXadesDSigCtxPtr
|
||||
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx) {
|
||||
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx) {
|
||||
xmlXadesDSigCtxPtr ctx = NULL;
|
||||
|
||||
ctx = malloc(sizeof(xmlXadesDSigCtx));
|
||||
@ -62,6 +24,8 @@ xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx) {
|
||||
}
|
||||
|
||||
ctx->dsigCtx = dsigCtx;
|
||||
ctx->digestMethod = digestMethod;
|
||||
ctx->policyCtx = policyCtx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@ -88,8 +52,18 @@ xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) {
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_n;
|
||||
// TODO(bit4bit) podemos obtener el digest de openssl por medio de la transformacion? o se puede usar la transformacion para generar el digest?
|
||||
xmlChar *digestMethod = (xmlChar *)xmlSecTransformSha256Id->href;
|
||||
const EVP_MD *digest = EVP_sha256();
|
||||
xmlChar *digestMethod = NULL;
|
||||
EVP_MD *digest = NULL;
|
||||
|
||||
switch(ctx->digestMethod) {
|
||||
case XADES_DIGEST_SHA256:
|
||||
digestMethod = (xmlChar *)xmlSecTransformSha256Id->href;
|
||||
digest = (EVP_MD *) EVP_sha256();
|
||||
break;
|
||||
default:
|
||||
xmlXadesInternalError("xmlXadesDSigCtxSign not known how to handle digest method.\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyDataX509, i);
|
||||
if ( cert == NULL ) {
|
||||
@ -144,6 +118,15 @@ xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) {
|
||||
OPENSSL_free(issuerNumber);
|
||||
}
|
||||
|
||||
// digest de policy identifier
|
||||
xmlNodePtr sigPolicyId = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyId/xades:Identifier[1]");
|
||||
if ( sigPolicyId == NULL ) {
|
||||
xmlXadesInternalError("xmlXadesXPathFirstElement(xades:SigPolicyId/xades:Identifier\n", NULL);
|
||||
return(-1);
|
||||
}
|
||||
xmlChar *identifier = xmlNodeListGetString(signNode->doc, sigPolicyId->xmlChildrenNode, 1);
|
||||
printf("IDENTIFIER %s\n", identifier);
|
||||
xmlFree(identifier);
|
||||
return xmlSecDSigCtxSign(ctx->dsigCtx, signNode);
|
||||
}
|
||||
|
||||
@ -157,3 +140,44 @@ xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx) {
|
||||
free(ctx);
|
||||
return(0);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath) {
|
||||
xmlXPathContextPtr xpathCtx;
|
||||
xmlXPathObjectPtr xpathResult;
|
||||
xmlNodePtr node;
|
||||
|
||||
// obtener QualifyingProteries
|
||||
|
||||
xpathCtx = xmlXPathNewContext(doc);
|
||||
/* register namespaces */
|
||||
// TOMADO DE: xmlsec1/src/xpath.c
|
||||
for(xmlNsPtr ns = xmlDocGetRootElement(doc)->nsDef; ns != NULL; ns = ns->next) {
|
||||
/* check that we have no other namespace with same prefix already */
|
||||
if((ns->prefix != NULL) && (xmlXPathNsLookup(xpathCtx, ns->prefix) == NULL)){
|
||||
int ret = xmlXPathRegisterNs(xpathCtx, ns->prefix, ns->href);
|
||||
if(ret != 0) {
|
||||
xmlXadesXmlError2("xmlXPathRegisterNs", NULL,
|
||||
"prefix=%s", xmlSecErrorsSafeString(ns->prefix));
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xpathResult = xmlXPathEvalExpression(BAD_CAST "//ds:Object/xades:QualifyingProperties[1]", xpathCtx);
|
||||
if ( xmlXPathNodeSetIsEmpty( xpathResult->nodesetval ) ) {
|
||||
xmlXadesInternalError("can't find ds:Signature/ds:Object/xades:QualifyingProperties \n", NULL);
|
||||
xmlXPathFreeObject(xpathResult);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// obtener puntero a nodo
|
||||
node = xpathResult->nodesetval->nodeTab[0];
|
||||
if ( node->type != XML_ELEMENT_NODE ) {
|
||||
xmlXadesInternalError("expected element QualifyingProperties\n", NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifndef XADES_H
|
||||
#define XADES_H
|
||||
|
||||
|
||||
|
||||
#include <libxml/tree.h>
|
||||
|
||||
#include <xmlsec/xmltree.h>
|
||||
@ -42,7 +40,7 @@ static const xmlChar xmlXadesNodeCert[] = "Cert";
|
||||
static const xmlChar xmlXadesNodeCertDigest[] = "CertDigest";
|
||||
static const xmlChar xmlXadesNodeSignaturePolicyIdentifier[] = "SignaturePolicyIdentifier";
|
||||
static const xmlChar xmlXadesNodeSignaturePolicyId[] = "SignaturePolicyId";
|
||||
static const xmlChar xmlXadesNodeSigPolicyId[] = "SignaturePolicyId";
|
||||
static const xmlChar xmlXadesNodeSigPolicyId[] = "SigPolicyId";
|
||||
static const xmlChar xmlXadesNodeIdentifier[] = "Identifier";
|
||||
static const xmlChar xmlXadesNodeDescription[] = "Description";
|
||||
static const xmlChar xmlXadesNodeSigPolicyHash[] = "SigPolicyHash";
|
||||
@ -56,14 +54,28 @@ static const xmlChar xmlXadesNodeX509IssuerNumber[] = "X509IssuerNumber";
|
||||
|
||||
static const xmlChar xmlXadesDSigNs[] = "http://uri.etsi.org/01903/v1.3.2#";
|
||||
|
||||
typedef int xmlXadesSize;
|
||||
typedef enum _XADES_DIGEST_METHOD{
|
||||
XADES_DIGEST_SHA256
|
||||
} XADES_DIGEST_METHOD;
|
||||
|
||||
typedef int (*xmlXadesPolicyIdentifierContentCallback)(const xmlChar *policyId, xmlChar *content, xmlXadesSize *content_length);
|
||||
|
||||
typedef struct _xmlXadesPolicyIdentifierCtx *xmlXadesPolicyIdentifierCtxPtr;
|
||||
struct _xmlXadesPolicyIdentifierCtx {
|
||||
XADES_DIGEST_METHOD digestMethod;
|
||||
xmlXadesPolicyIdentifierContentCallback contentCallback;
|
||||
};
|
||||
|
||||
typedef struct _xmlXadesDSigCtx xmlXadesDSigCtx, *xmlXadesDSigCtxPtr;
|
||||
struct _xmlXadesDSigCtx {
|
||||
xmlSecDSigCtxPtr dsigCtx;
|
||||
XADES_DIGEST_METHOD digestMethod;
|
||||
xmlXadesPolicyIdentifierCtxPtr policyCtx;
|
||||
};
|
||||
|
||||
|
||||
xmlXadesDSigCtxPtr
|
||||
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx);
|
||||
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx);
|
||||
|
||||
int
|
||||
xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode);
|
||||
@ -74,35 +86,37 @@ xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx);
|
||||
xmlNodePtr
|
||||
xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplQualifyingPropertiesCreateNsPref(xmlDocPtr doc, const xmlChar* id, const xmlChar* nsPrefix);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigningCertificate(xmlNodePtr parentNode, xmlSecTransformId digestMethodId);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddCertDigest(xmlNodePtr signingCertificateNode, const xmlChar *digestMethod, const xmlChar *digestValue);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr parentNode, struct tm* signingTime);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignaturePolicyIdentifierSignaturePolicyId(xmlNodePtr signedSignaturePropertiesNode);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr parentNode, struct tm* signingTime);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber);
|
||||
|
||||
xmlNodePtr
|
||||
xmlXadesAddChildRecursiveNs(xmlNodePtr parentNode, const xmlChar* path, const xmlChar* nsPrefix);
|
||||
#endif //XADES_H
|
||||
|
Loading…
Reference in New Issue
Block a user