EldoS | Feel safer!

Software components for data protection, secure storage and transfer

[Java] Signing certificate invalid on XAdES signatures

Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.
#33712
Posted: 06/19/2015 04:45:20
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Hello.

I'd like to know in what cases TElXAdESVerifier.Validate() returns that the signing certificate as invalid or incomplete. FYI, the certificate used in on a smart card and isn't expired.

Furthermore, I tried to verify the signature with the sample SimpleSigner and the result is the same.

Here are my signing function :
Code
TElXMLDOMDocument xml            = new TElXMLDOMDocument();
xml.LoadFromFile( this._fileToSign.getAbsolutePath() );
TElMemoryCertStorage certStorage   = new TElMemoryCertStorage();
TElXMLReferenceList xmlRefsList      = new TElXMLReferenceList();
TElXMLReference xmlRef            = new TElXMLReference();
TElStream fileStream            = null;
TElXAdESSigner xadesSigner         = null;
TElXMLSigner signer               = null;
String documentId               = xml.GetDocumentElement().GetAttribute("Id");
String sigId                  = documentId + "_SIG_1";

try {
   if ( documentId.isEmpty() || documentId == null ) {
      xml.GetDocumentElement().SetAttribute( "Id", "AWS_DocumentRootID");
      
      documentId   = xml.GetDocumentElement().GetAttribute("Id");
      sigId      = documentId + "_SIG_1";
   }
   
   fileStream = new TElFileStream(this._fileToSign.getAbsolutePath(), "r", true);
   
   xmlRef.SetDigestMethod( SBXMLSec.xdmSHA1 );
   xmlRef.SetURI( "#" + documentId );
   xmlRef.SetURINode( xml.GetDocumentElement() );
   xmlRef.SetURIStream( fileStream );
   xmlRef.SetURIStreamOffset( 0 );
   xmlRef.SetURIStreamCount( fileStream.GetLength() );
   xmlRef.GetTransformChain().Add( new TElXMLEnvelopedSignatureTransform() );
   xmlRef.GetTransformChain().Add( new TElXMLC14NTransform(SBXMLDefs.xcmExclCanon) );

   xmlRefsList.Add(xmlRef);
   
   TElWinCertStorage winCertStorage = new TElWinCertStorage();
   winCertStorage.Clear();
   winCertStorage.GetSystemStores().Add( "MY" );
   
   certStorage.Clear();
   certStorage.Add(this._telX509Cert, true);
   
   System.out.println("Certificats de signature :");
   for (int i = 0; i < certStorage.GetCount(); i++) {
      TElX509Certificate cert   = certStorage.GetCertificate(i);
      
      System.out.println("\t- " + cert.GetSubjectName().CommonName + " ( " + Divers.byte2String( cert.GetSerialNumber() ) + " )");
   }
   
   String pesType      = "EnTeteDepense";
   TElXMLDOMNode node   = xml.GetDocumentElement().FindNode( pesType, true );
   
   if ( node == null ) {
      pesType   = "EnTeteRecette";
      node   = xml.GetDocumentElement().FindNode( pesType, true );
   }

   if ( node == null ) {
      pesType   = "EnTeteRole";
      node   = xml.GetDocumentElement().FindNode( pesType, true );
   }

   if ( node == null ) {
      pesType   = "EnTeteBudget";
      node   = xml.GetDocumentElement().FindNode( pesType, true );
   }

   if ( node == null ) {
      pesType   = "EnTeteMarche";
      node   = xml.GetDocumentElement().FindNode( pesType, true );
   }
   
   if ( node == null ) {
      pesType   = "EnTetePES_PJ";
      node   = xml.GetDocumentElement().FindNode( pesType, true );
   }
   
   if ( pesType != "EnTetePES_PJ" ) {
      TElXMLDOMNode nodeInfoDemat = node.FindNode( "InfoDematerialisee" );
      
      if ( nodeInfoDemat == null ) {
         System.out.println( "nodeInfoDemat == null" );
         
         TElXMLDOMElement newElement = xml.CreateElement( "InfoDematerialisee" );
         newElement.SetAttribute( "V", "1" );
         node.AppendChild( newElement );
         
         System.out.println( "Noeud ajouté : V = " + newElement.GetAttribute("V") );
      }
      else {
         System.out.println( "nodeInfoDemat != null" );
         
         TElXMLDOMNamedNodeMap attribs = nodeInfoDemat.GetAttributes();
         for ( int i = 0; i < attribs.GetLength(); i++ ) {
            TElXMLDOMNode attr = attribs.GetItem(i);
            
            if ( attr.GetNodeName().equals("V") && attr.GetNodeValue().equals("0") ) {
               attr.SetNodeValue( "1" );
               System.out.println( "Noeud modifié : " + attr.GetNodeName() + " = " + attr.GetNodeValue() );
            }
         }
      }
   }
   
   TElX509CertificateValidator certValidator = new TElX509CertificateValidator();
   
   // The following lines are required for HTTP retrieval of CRLs and OCSP in TElX509CertificateValidator to work
   SBHTTPCRL.RegisterHTTPCRLRetrieverFactory();
   SBLDAPCRL.RegisterLDAPCRLRetrieverFactory();
   SBHTTPOCSPClient.RegisterHTTPOCSPClientFactory();
   SBHTTPCertRetriever.RegisterHTTPCertificateRetrieverFactory();

   certValidator.InitializeWinStorages();
   certValidator.SetCheckOCSP( true );
   certValidator.SetMandatoryOCSPCheck( true );
   certValidator.SetOnBeforeCertificateValidation( new TSBBeforeCertificateValidationEvent(this._onBeforeCertificateValidation) );
   certValidator.SetOnCRLRetrieved( new TSBCRLRetrievedEvent(this._onCRLRetrieved) );
   certValidator.SetOnOCSPResponseSignerValid( new TSBOCSPResponseSignerValidEvent(this._onOCSPResponseSignerValid) );
   
   xadesSigner = new TElXAdESSigner();
   xadesSigner.SetXAdESVersion( SBXMLAdES.XAdES_v1_1_1 );
   xadesSigner.SetXAdESForm( SBXMLAdES.XAdES );
   xadesSigner.SetSigningCertificates( certStorage );
   xadesSigner.SetCertificateValidator( certValidator );
   xadesSigner.SetSigningTime( DateUtil.getDateTimeUTCNow() );
   xadesSigner.SetTSPClient( null );
   xadesSigner.SetIgnoreTimestampFailure( true );
   xadesSigner.SetIgnoreChainValidationErrors( true );
   xadesSigner.SetIncluded( SBXMLAdESIntf.xipProductionPlace | SBXMLAdESIntf.xipSignerRole );
   
   xadesSigner.SetOnBeforeCertificateValidate( new TSBXAdESBeforeCertificateValidateEvent(this._onBeforeCertificateValidate) );
   
   String policyURL      = AppletAWS.getConfig( "sig.xades.helios.policy.url" );
   String policyID         = AppletAWS.getConfig( "sig.xades.helios.policy.id" );
   String policyHash      = AppletAWS.getConfig( "sig.xades.helios.policy.hash" );
   
   TElXMLAnyType item = new TElXMLAnyType( xadesSigner.GetXAdESVersion() );
   item.SetValue( xml.CreateElement("temp") ); // use new node or cloned node, works as container for xml tree
   TElXMLDOMElement innerElement = xml.CreateElement( "xad:SPURI" );
   item.GetValue().AppendChild( innerElement );
   innerElement.AppendChild( xml.CreateTextNode(policyURL) );
   
   xadesSigner.GetPolicyId().GetSigPolicyId().SetIdentifier( policyID );
   xadesSigner.GetPolicyId().GetSigPolicyId().SetDescription( "Politique de signature Helios de la DGFiP" );
   xadesSigner.GetPolicyId().GetSigPolicyHash().SetDigestMethod( SBXMLSec.DigestMethodToURI(SBXMLSec.xdmSHA1) );
   xadesSigner.GetPolicyId().GetSigPolicyHash().SetDigestValue( SBUtils.BytesOfString(SBEncoding.Base64DecodeString(policyHash)) );   // Hash en cache.
   xadesSigner.GetPolicyId().GetSigPolicyQualifiers().Add( item );
   
   if (policyID.length() > 0) {
      if (policyID.substring(0, 4).toLowerCase().compareTo("urn:") == 0) {
         xadesSigner.GetPolicyId().GetSigPolicyId().SetIdentifierQualifier( SBXMLAdES.xqtOIDAsURN );
      }
      else {
         xadesSigner.GetPolicyId().GetSigPolicyId().SetIdentifierQualifier( SBXMLAdES.xqtOIDAsURI );
      }
   }
   else {
      xadesSigner.GetPolicyId().GetSigPolicyId().SetIdentifierQualifier( SBXMLAdES.xqtNone );
   }
   
   xadesSigner.Generate( SBXMLAdES.XAdES );
   
   /*
    * Setting Qualifying Properties.
    */
   xadesSigner.GetQualifyingProperties().SetXAdESPrefix( "xad" );
   xadesSigner.GetQualifyingProperties().SetTarget( sigId );
   xadesSigner.GetQualifyingProperties().GetSignedProperties().SetID( sigId + "_SP" );
   xadesSigner.GetQualifyingProperties().GetUnsignedProperties().GetUnsignedSignatureProperties().GetCertificateValues().GetEncapsulatedX509Certificates().AddCertificate( this._telX509Cert, xadesSigner.GetXAdESVersion() );
   xadesSigner.GetQualifyingProperties().GetUnsignedProperties().GetUnsignedSignatureProperties().GetCompleteCertificateRefs().GetCertRefs().AddCertificate( this._telX509Cert, xadesSigner.GetXAdESVersion() );

   signer = new TElXMLSigner();
   signer.SetReferences( xmlRefsList );
   signer.SetIncludeKey( true );
   signer.SetCanonicalizationMethod( SBXMLDefs.xcmExclCanon );
   signer.SetSignatureType( SBXMLSec.xstEnveloped );
   signer.SetSignatureMethodType( SBXMLSec.xmtSig );
   signer.SetSignatureMethod( SBXMLSec.xsmRSA_SHA1 );
   signer.SetXAdESProcessor( xadesSigner );

   if ( (signer.GetSignatureType() == SBXMLSec.xstEnveloping) && (xmlRef != null) && xmlRef.GetURI().equals("") && (xmlRef.GetURINode() instanceof TElXMLDOMElement) ) {
      TElXMLDOMElement el = (TElXMLDOMElement) xmlRef.GetURINode();
      el.SetAttribute( "Id", "id-" + SBStrUtils.IntToStr(SBRandom.SBRndGenerate(Integer.MAX_VALUE)) );
      xmlRef.SetURI( "#" + el.GetAttribute("Id") );
   }
   
   if ( this._telX509Cert.GetPrivateKeyExists() ) {
      TElXMLKeyInfoX509Data X509KeyData = new TElXMLKeyInfoX509Data(false);
      X509KeyData.SetCertificate(this._telX509Cert);
      signer.SetKeyData(X509KeyData);
   }

   signer.UpdateReferencesDigest();
   signer.GenerateSignature();
   
   TElXMLSignature sig   = signer.GetSignature();
   sig.SetID( sigId );
   sig.GetSignatureValue().SetID( sigId + "_SV" );
   sig.GetKeyInfo().SetID( sigId + "_KI" );
   sig.GetQualifyingProperties().GetSignedProperties().GetSignedSignatureProperties().SetID( null );
   
   TElXMLReference signedInfoRef = sig.GetSignedInfo().GetSigPropRef();
   signedInfoRef.SetURI( "#" + sigId + "_SP" );
   signedInfoRef.GetTransformChain().Add( new TElXMLEnvelopedSignatureTransform() );
   signedInfoRef.GetTransformChain().Add( new TElXMLC14NTransform(SBXMLDefs.xcmExclCanon) );
   
   String sigFilePath = "";
   if (signer.GetSignatureType() == SBXMLSec.xstDetached) {
      xml.Destroy();
      
      try {
         TElXMLDOMNode nodeToSign      = null;
         TSBObject obj   = new TSBObject();
         signer.Save( obj );
         nodeToSign = (TElXMLDOMNode) obj.Value;
         
         xml         = nodeToSign.GetOwnerDocument();
         sigFilePath   = this._fileToSign.getParent() + System.getProperty("file.separator") + this._fileToSign.getName().substring(0, this._fileToSign.getName().length() - 4) + "_signed-detached.xml";
         
         XAdES.saveToFile( xml, sigFilePath );
      }
      catch (Exception e) {
         throw e;
      }
   }
   else {
      TElXMLDOMNode nodeToSign = (TElXMLDOMNode) xml.GetDocumentElement();
      if (nodeToSign instanceof TElXMLDOMDocument) {
         nodeToSign = ((TElXMLDOMDocument) nodeToSign).GetDocumentElement();
      }

      try {
         // If the signature type is enveloping, then the signature is placed into the passed node and the contents of the node are moved to inside of the signature.
         // If the signature type is enveloped, the signature is placed as a child of the passed node.
         TSBObject obj   = new TSBObject();
         obj.Value      = nodeToSign;
         signer.Save( obj );
         
         TSBXAdESValidity validityDataRefs   = xadesSigner.AddValidationDataRefs( this._telX509Cert, true, true, SBXMLSec.xdmSHA1, true, null );
         TSBXAdESValidity validityDataValues   = xadesSigner.AddValidationDataValues( this._telX509Cert, true, true, null );
         
         TElXMLDOMNode nodeToRemove = sig.GetQualifyingProperties().GetUnsignedProperties().GetXMLElement();
         if ( nodeToRemove != null ) {
            sig.GetQualifyingProperties().GetXMLElement().RemoveChild( nodeToRemove );
         }
         
         System.out.println( "\n" + validityDataRefs.toString() );
         System.out.println( validityDataValues.toString() + "\n" );
         
         sigFilePath = this._fileToSign.getParent() + System.getProperty("file.separator") + this._fileToSign.getName().substring(0, this._fileToSign.getName().length() - 4);
         if (signer.GetSignatureType() == SBXMLSec.xstEnveloped) {
            sigFilePath += "_signed-enveloped.xml";
         }
         else {
            sigFilePath += "_signed-enveloping.xml";
         }
         
         XAdES.saveToFile( xml, sigFilePath );
      }
      catch (Exception e) {
         throw e;
      }
   }
}
catch ( Exception e ) {
   // Dealing with errors...
}


Verifying function :
Code
TElXMLDOMDocument xml   = new TElXMLDOMDocument();
xml.LoadFromFile(this._fileSignature.getAbsolutePath());

TElXAdESVerifier xadesVerifier   = new TElXAdESVerifier();
xadesVerifier.SetIgnoreChainValidationErrors(true);
TElXMLVerifier xmlVerifier      = new TElXMLVerifier();
TElXMLDOMNode sigNode         = xml.GetDocumentElement();

xmlVerifier.SetXAdESProcessor(xadesVerifier);

try {
   xmlVerifier.Load((TElXMLDOMElement) sigNode);
}
catch (Exception e) {
   if (e instanceof SecureBlackbox.XML.EElXMLSecurityError) {
      throw new SignatureInvalidException("Fichier non signé.");
   }
   
   throw e;
}

boolean signValid = xmlVerifier.ValidateSignature();
if (!signValid) {
   throw new Exception( "Signature invalide." );
}

AppletAWS.println("Signature valid ! Checking XAdES data...");

TElXAdESVerifierResult xadesRes = null;
try {
   xadesRes = xadesVerifier.Validate();
}
catch (Exception e) {
   throw e;
}

Date sigDate = DateUtil.convertDateUTCToLocaleDate( xadesVerifier.GetSigningTime() );
AppletAWS.println("Signing date : " + df.format(sigDate));

if (xadesRes.Validity == TSBXAdESValidity.xsvValid) {
   // XAdES data valid, verying certificate, etc.
}
else {
   String exTxt = "";
   if (xadesRes.Validity == TSBXAdESValidity.xsvInvalid) {
      exTxt += "Signature invalide : " + XAdES.XAdESReasonsToString(xadesRes.Reasons);
   }
   else if (xadesRes.Validity == TSBXAdESValidity.xsvIncomplete) {
      exTxt += "Signature incomplète : " + XAdES.XAdESReasonsToString(xadesRes.Reasons);
   }
   else {
      exTxt += "Echec de la vérification, une erreur inconnue s'est produite.";
   }
   
   throw new Exception(exTxt);
}


And XAdESReasonsToString function :
Code
public static String XAdESReasonsToString(int reasons) {
   String reason = "";

   if ((reasons & SBXMLAdESIntf.xvrNotSigned) > 0) {
      reason += "Not Signed, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrNoSigningCertificate) > 0) {
      reason += "No Signing Certificate, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSigningCertificateNotSigned) > 0) {
      reason += "Signing Certificate Not Signed, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSigningCertificateIncomplete) > 0) {
      reason += "Signing Certificate Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSigningCertificateInvalid) > 0) {
      reason += "Signing Certificate Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrIndividualDataObjectsTimestampInvalid) > 0) {
      reason += "Individual Data Objects Timestamp Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrIndividualDataObjectsTimestampIncomplete) > 0) {
      reason += "Individual Data Objects Timestamp Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrAllDataObjectsTimestampInvalid) > 0) {
      reason += "All Data Objects Timestamp Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrAllDataObjectsTimestampIncomplete) > 0) {
      reason += "All Data Objects Timestamp Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSignatureTimestampInvalid) > 0) {
      reason += "Signature Timestamp Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSignatureTimestampIncomplete) > 0) {
      reason += "Signature Timestamp Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrRefsOnlyTimestampInvalid) > 0) {
      reason += "References Only Timestamp Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrRefsOnlyTimestampIncomplete) > 0) {
      reason += "References Only Timestamp Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSigAndRefsTimestampInvalid) > 0) {
      reason += "Signature And References Timestamp Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrSigAndRefsTimestampIncomplete) > 0) {
      reason += "Signature And References Timestamp Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrArchiveTimestampInvalid) > 0) {
      reason += "Archive Timestamp Invalid, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrArchiveTimestampIncomplete) > 0) {
      reason += "Archive Timestamp Incomplete, ";
   }

   if ((reasons & SBXMLAdESIntf.xvrInternalError) > 0) {
      reason += "Internal Error, ";
   }

   if ( (reason != null && !reason.equals("")) && (reason.length() > 2) ) {
      return reason.substring(0, reason.length() - 2);
   }
   else {
      return reason;
   }
}


Thank you.
#33713
Posted: 06/19/2015 06:24:14
by Dmytro Bogatskyy (EldoS Corp.)

Thank you for contacting us.

Quote
I'd like to know in what cases TElXAdESVerifier.Validate() returns that the signing certificate as invalid or incomplete. FYI, the certificate used in on a smart card and isn't expired.

This validity reason could be reported if the component fails to validate signing certificate, for example: if some of intermediate certificates are not available to the component, if CA certificate is not in the trusted certificate list, or if some certificate in the chain is invalid (e.g. expired), or if some CRL or OCSP response failed to retrieve (if they are required and you don't have set other validation options).
TElXAdESVerifier class internally uses TElX509CertificateValidator class to validate certificates. You can set own instance of TElCertificateValidator class using TElXAdESSigner/TElXAdESVerifier.CertificateValidator property or the component will create an own instance of the validator internally and you can modify its options in TElXAdESSigner/TElXAdESVerifier.OnBeforeCertificateValidate event handler (please see: XMLBlackbox\AdvancedSigner sample in C# or VCL edition). Also please refer to the following article: https://www.eldos.com/documentation/sb...dator.html
#33728
Posted: 06/22/2015 08:55:04
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

OK I tried that :

Code
public static TSBXAdESBeforeCertificateValidateEvent.Callback onBeforeCertificateValidate = new TSBXAdESBeforeCertificateValidateEvent.Callback() {
      
   @Override
   public void TSBXAdESBeforeCertificateValidateEventCallback(TObject sender, TElX509Certificate cert, TElX509CertificateValidator certValidator) {
      // The following lines are required for HTTP retrieval of CRLs and OCSP in TElX509CertificateValidator to work
      SBHTTPCRL.RegisterHTTPCRLRetrieverFactory();
      SBLDAPCRL.RegisterLDAPCRLRetrieverFactory();
      SBHTTPOCSPClient.RegisterHTTPOCSPClientFactory();
      SBHTTPCertRetriever.RegisterHTTPCertificateRetrieverFactory();
      
      certValidator.ClearBlockedCertificates();
      certValidator.ClearKnownCertificates();
      certValidator.ClearKnownCRLs();
      certValidator.ClearKnownOCSPResponses();
      certValidator.ClearTrustedCertificates();
      
      certValidator.InitializeWinStorages();
      certValidator.SetUseSystemStorages( true );
      certValidator.SetIgnoreSystemTrust( false );
      certValidator.SetCheckCRL( false );
      certValidator.SetMandatoryCRLCheck( false );
      certValidator.SetCheckOCSP( false );
      certValidator.SetMandatoryOCSPCheck( false );
      certValidator.SetValidateInvalidCertificates( true );
   }
   
};

Code
xadesVerifier.SetOnBeforeCertificateValidate( new TSBXAdESBeforeCertificateValidateEvent(XAdES.onBeforeCertificateValidate) );

But the result's still the same, the certificate is invalid for some reasons.

Something I didn't mention before, the certificate that is said invalid was used a few days before to perform signatures and there was no problem at the time. Seems like it changed from one day to another.

Do you have any clue on how I should/could process ?
#33732
Posted: 06/22/2015 09:53:40
by Dmytro Bogatskyy (EldoS Corp.)

Hello,
Quote
But the result's still the same, the certificate is invalid for some reasons.

Something I didn't mention before, the certificate that is said invalid was used a few days before to perform signatures and there was no problem at the time. Seems like it changed from one day to another.

Do you have any clue on how I should/could process ?

As you have disabled CRL and OCSP checking, the possible reasons of invalid result are: invalid certificate, no intermediate or CA certificate available, CA certificate is not trusted.
To identify the exact reason why signing certificate is invalid you would need to get a full log of certificate validation.
If you are using the latest pre-release SecureBlackbox version 13 and you are assigning a custom certificate validator to TElXAdESVerifier.CertificateValidator property, then after XAdES validation you can get a full certificate validation log using CertificateValidator.InternalLogger.Log property.
For the older version, you would need to implement own OnBeforeCertificateValidation, OnAfterCertificateValidation, OnCACertificateNeeded, OnCACertificateRetrieved event handlers and log passed certificates and validation result/reason. You can add those callbacks in your TSBXAdESBeforeCertificateValidateEventCallback method. To identify the exact reason, why your signing certificate is invalid, implementing OnAfterCertificateValidation event handler may be enough.
#33734
Posted: 06/22/2015 11:45:10
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Indeed OnAfterCertificateValidation was enough. The CA of the certificate wasn't installed on my computer, that's all.

Thanks for your help !
Also by EldoS: Solid File System
A virtual file system that offers a feature-rich storage for application documents and data with built-in compression and encryption.

Reply

Statistics

Topic viewed 1003 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!