Hola a todos.
Como ya he comentado el problema radica que con este tipo de certificados de representación hay que firmar el fichero varias veces. Despues de varios días hablando con los de SecureBlackBox parece que hemos encontrado la solución. Pongo la solución para firmar con estos certificados y la anterior.
Código Delphi
[-]procedure SignFacturaRepresentacion(XMLDocument : TElXMLDOMDocument; Cert : TElX509Certificate);
var
Signer : TElXMLSigner;
XAdESSigner: TElXAdESSigner;
X509KeyInfoData: TElXMLKeyInfoX509Data;
DataFormat : TElXMLDataObjectFormat;
Ref : TElXMLReference;
URL : string;
Buf : ByteArray;
k, i : Integer;
CertificateValidator : TElX509CertificateValidator;
Validity : TSBCertificateValidity;
Reason : TSBCertificateValidityReason;
begin
Signer := TElXMLSigner.Create(nil);
XAdESSigner := TElXAdESSigner.Create(nil);
X509KeyInfoData := TElXMLKeyInfoX509Data.Create(true);
try
Signer.XAdESProcessor := XAdESSigner;
Signer.SignatureMethodType := xmtSig;
Signer.SignatureMethod := xsmRSA_SHA256;
Signer.CanonicalizationMethod := xcmCanon;
Signer.IncludeKey := true;
k := Signer.References.Add;
Ref := Signer.References[k];
Ref.DigestMethod := xdmSHA512;
Ref.ID := 'Ref1';
Ref.URI := '';
Ref.URINode := XMLDocument.DocumentElement;
Ref.TransformChain.AddEnvelopedSignatureTransform();
Signer.UpdateReferencesDigest();
k := Signer.References.Add;
Ref := Signer.References[k];
Ref.DigestMethod := xdmSHA512;
Ref.URI := '#Certificate1';
XAdESSigner.XAdESVersion := XAdES_v1_3_2;
XAdESSigner.Included := [xipSignerRole];
XAdESSigner.SigningTime := UTCNow;
XAdESSigner.SignerRole.ClaimedRoles.AddText(XAdESSigner.XAdESVersion, XMLDocument, 'emisor');
URL := 'http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf';
XAdESSigner.PolicyId.SigPolicyId.Identifier := URL;
XAdESSigner.PolicyId.SigPolicyId.IdentifierQualifier := xqtNone;
XAdESSigner.PolicyId.SigPolicyHash.DigestMethod := DigestMethodToURI(xdmSHA1);
XAdESSigner.PolicyId.SigPolicyHash.DigestValue := ConvertFromBase64String('Ohixl6upD6av8N7pEvDABhEL6hM=');
XAdESSigner.SigningCertificates := TElMemoryCertStorage.Create(nil);
XAdESSigner.OwnSigningCertificates := true;
XAdESSigner.SigningCertificates.Add(Cert);
XAdESSigner.SigningCertificatesDigestMethod := xdmSHA512;
XAdESSigner.SignedPropertiesReferenceDigestMethod := xdmSHA512;
XAdESSigner.Generate(XAdES_EPES);
XAdESSigner.QualifyingProperties.XAdESPrefix := 'xades';
XAdESSigner.QualifyingProperties.ID := 'QualifyingPropertiesId';
DataFormat := TElXMLDataObjectFormat.Create(XAdESSigner.XAdESVersion);
DataFormat.MimeType := 'text/xml';
DataFormat.ObjectReference := '#Ref1';
XAdESSigner.QualifyingProperties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Add(D ataFormat);
X509KeyInfoData.IncludeKeyValue := true;
X509KeyInfoData.IncludeDataParams := [xkidX509Certificate];
X509KeyInfoData.CertStorage := TElMemoryCertStorage.Create(nil);
X509KeyInfoData.CertStorage.Add(Cert);
CertificateValidator := TElX509CertificateValidator.Create(nil);
CertificateValidator.CheckCRL := false;
CertificateValidator.CheckOCSP := false;
CertificateValidator.ImplicitlyTrustSelfSignedCertificates := true;
CertificateValidator.Validate(cert, Validity, Reason);
for i := 1 to (CertificateValidator.UsedCertificates.Count - 1) do
begin
X509KeyInfoData.CertStorage.Add(CertificateValidator.UsedCertificates.Certificates[i]);
end;
Signer.KeyData := X509KeyInfoData;
Signer.GenerateSignature;
Signer.Signature.KeyInfo.ID := 'Certificate1';
Signer.SaveEnveloped(XMLDocument.DocumentElement);
finally
FreeAndNil(X509KeyInfoData);
FreeAndNil(Signer);
FreeAndNil(XAdESSigner);
FreeAndNil(CertificateValidator);
end;
end;
Código Delphi
[-]procedure SignFactura(XMLDocument : TElXMLDOMDocument; Cert : TElX509Certificate);
var
Signer : TElXMLSigner;
XAdESSigner: TElXAdESSigner;
X509KeyInfoData: TElXMLKeyInfoX509Data;
DataFormat : TElXMLDataObjectFormat;
Ref : TElXMLReference;
URL : string;
Buf : ByteArray;
k : Integer;
begin
Signer := TElXMLSigner.Create(nil);
XAdESSigner := TElXAdESSigner.Create(nil);
X509KeyInfoData := TElXMLKeyInfoX509Data.Create(false);
try
Signer.XAdESProcessor := XAdESSigner;
Signer.SignatureMethodType := xmtSig;
Signer.SignatureMethod := xsmRSA_SHA256;
Signer.CanonicalizationMethod := xcmCanon;
Signer.IncludeKey := true;
k := Signer.References.Add;
Ref := Signer.References[k];
Ref.DigestMethod := xdmSHA512;
Ref.ID := 'Ref1';
Ref.URI := '';
Ref.URINode := XMLDocument.DocumentElement;
Ref.TransformChain.AddEnvelopedSignatureTransform();
Signer.UpdateReferencesDigest();
k := Signer.References.Add;
Ref := Signer.References[k];
Ref.DigestMethod := xdmSHA512;
Ref.URI := '#Certificate1';
XAdESSigner.XAdESVersion := XAdES_v1_3_2;
XAdESSigner.Included := [xipSignerRole];
XAdESSigner.SigningTime := UTCNow;
XAdESSigner.SignerRole.ClaimedRoles.AddText(XAdESSigner.XAdESVersion, XMLDocument, 'emisor');
URL := 'http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf';
XAdESSigner.PolicyId.SigPolicyId.Identifier := URL;
XAdESSigner.PolicyId.SigPolicyId.IdentifierQualifier := xqtNone;
XAdESSigner.PolicyId.SigPolicyHash.DigestMethod := DigestMethodToURI(xdmSHA1);
XAdESSigner.PolicyId.SigPolicyHash.DigestValue := ConvertFromBase64String('Ohixl6upD6av8N7pEvDABhEL6hM=');
XAdESSigner.SigningCertificates := TElMemoryCertStorage.Create(nil);
XAdESSigner.OwnSigningCertificates := true;
XAdESSigner.SigningCertificates.Add(Cert);
XAdESSigner.SigningCertificatesDigestMethod := xdmSHA512;
XAdESSigner.SignedPropertiesReferenceDigestMethod := xdmSHA512;
XAdESSigner.Generate(XAdES_EPES);
XAdESSigner.QualifyingProperties.XAdESPrefix := 'xades';
XAdESSigner.QualifyingProperties.ID := 'QualifyingPropertiesId';
DataFormat := TElXMLDataObjectFormat.Create(XAdESSigner.XAdESVersion);
DataFormat.MimeType := 'text/xml';
DataFormat.ObjectReference := '#Ref1';
XAdESSigner.QualifyingProperties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Add(D ataFormat);
X509KeyInfoData.IncludeKeyValue := true;
X509KeyInfoData.IncludeDataParams := [xkidX509Certificate];
X509KeyInfoData.Certificate := Cert;
Signer.KeyData := X509KeyInfoData;
Signer.GenerateSignature;
Signer.Signature.KeyInfo.ID := 'Certificate1';
Signer.SaveEnveloped(XMLDocument.DocumentElement);
finally
FreeAndNil(X509KeyInfoData);
FreeAndNil(Signer);
FreeAndNil(XAdESSigner);
end;
end;
Antes de llamar a una función de firma u otra se mira si el certificado es de representación.
Código Delphi
[-]if AnsiPos(Ansiuppercase('REPRESENTACIÓN'), ANSIUPPERCASE(Cert.IssuerName.CommonName)) = 0 then
SignFactura(FXMLDocument, FCertificate) else
SignFacturaRepresentacion(FXMLDocument, FCertificate);
De todas formas todo esto viene por que facturas que antes daban correcto en la página de hacienda de facturae
https://www.facturae.gob.es ahora dan incorrecto. He podido comprobar que en otras páginas del gobierno como
https://face.gob.es/es/facturas/vali...lizar-facturas, las facturas siguen dando correcto. Asi que parece que es una validación que han añadido en la primera página.