Discuss this help topic in SecureBlackbox Forum

Validate XML signature

To validate XML digital signature you should perform the following steps:

  1. Traverse the loaded signatures using SignatureHandlerCount and SignatureHandlers[] properties of TElOfficeDocument class.
  2. Check the type of signature handler and call Validate() method to validate the signature.
  3. Call handler's Validate() method, which will perform signature validation and return its result.
  4. If the Validate() method returns ValidButNotParts or ValidButNotEntries result, this means, that the signature itself is valid and has not been modified, but some of document parts/entries were modified.
    You can use SignedPartCount/SignedParts[] or SignedEntryCount/SignedEntries[] properties of the handler to traverse document parts/entries and get validation status details for each using ValidationStatus property of the object returned by SignedParts/SignedEntries[index] property.
  5. If Validate() method returns Valid result, then you should perform signer certificate validation and/or XAdES information validation.

To check, whether the signature contains XAdES information, you should check the value of signature handler's XAdESProcessor property. If the property is not null/nil/Nothing, then you should cast the object to TElXAdESVerifier and check if TElXAdESVerifier.IsEnabled property is true. After that, if IsEnabled property is true, you should call TElXAdESVerifier.Validate() method to validate both the XAdES signature and a signer certificate.

Otherwise, if there is no XAdES information available, you should get the signer certificate using signature handler's SignerCertificate property, and then use TElX509CertificateValidator class to validate a certificate. You can get additional (intermediate) certificates using Certificates property.

C#:


bool ValidateSignature(string sourceFilename)
{
    using (TElOfficeDocument Document = new TElOfficeDocument())
    {
        Document.Open(sourceFilename);
        if (!Document.IsSigned)
            throw new Exception("Document is not signed");

        bool Result = true;
        for (int i = 0; i < Document.SignatureHandlerCount; i++)
        {
            TElOfficeCustomSignatureHandler Handler = Document.get_SignatureHandlers(i);
            TElX509Certificate SignerCertificate = null;
            TElCustomCertStorage AdditionalCertificates = null;
            DateTime SignatureTime;
            TElXAdESVerifier XAdESVerifier = null;
            if (Handler is TElOfficeOpenXMLBaseSignatureHandler)
            {
                TElOfficeOpenXMLBaseSignatureHandler XMLSigHandler = (TElOfficeOpenXMLBaseSignatureHandler)Handler;
                TSBOfficeOpenXMLSignatureValidationStatus ValidationStatus = XMLSigHandler.Validate();
                Result = Result && (ValidationStatus == TSBOfficeOpenXMLSignatureValidationStatus.Valid);

                SignerCertificate = XMLSigHandler.SignerCertificate;
                AdditionalCertificates = XMLSigHandler.Certificates;
                SignatureTime = XMLSigHandler.SignatureTime.ValueUTC;
                if (XMLSigHandler.XAdESProcessor is TElXAdESVerifier)
                    XAdESVerifier = (TElXAdESVerifier)XMLSigHandler.XAdESProcessor;
            }
            else if (Handler is TElOfficeBinaryCryptoAPISignatureHandler)
            {
                TElOfficeBinaryCryptoAPISignatureHandler BinCryptoAPISigHandler = (TElOfficeBinaryCryptoAPISignatureHandler)Handler;
                TSBOfficeBinarySignatureValidationStatus BinValidationStatus = BinCryptoAPISigHandler.Validate();
                Result = Result && (BinValidationStatus == TSBOfficeBinarySignatureValidationStatus.Valid);

                SignerCertificate = BinCryptoAPISigHandler.Certificate;
                AdditionalCertificates = BinCryptoAPISigHandler.IntermediateCertificatesStorage;
                SignatureTime = BinCryptoAPISigHandler.SignTime;
            }
            else if (Handler is TElOfficeBinaryXMLSignatureHandler)
            {
                TElOfficeBinaryXMLSignatureHandler BinXMLSigHandler = (TElOfficeBinaryXMLSignatureHandler)Handler;
                TSBOfficeBinarySignatureValidationStatus BinValidationStatus = BinXMLSigHandler.Validate();
                Result = Result && (BinValidationStatus == TSBOfficeBinarySignatureValidationStatus.Valid);

                SignerCertificate = BinXMLSigHandler.SignerCertificate;
                AdditionalCertificates = BinXMLSigHandler.Certificates;
                SignatureTime = BinXMLSigHandler.SignatureTime.ValueUTC;
                if (BinXMLSigHandler.XAdESProcessor is TElXAdESVerifier)
                    XAdESVerifier = (TElXAdESVerifier)BinXMLSigHandler.XAdESProcessor;
            }
            else if (Handler is TElOpenOfficeSignatureHandler)
            {
                TElOpenOfficeSignatureHandler ODFSigHandler = (TElOpenOfficeSignatureHandler)Handler;
                TSBOpenOfficeSignatureValidationStatus ODFValidationStatus = ODFSigHandler.Validate();
                Result = Result && (ODFValidationStatus == TSBOpenOfficeSignatureValidationStatus.Valid);

                SignerCertificate = ODFSigHandler.SignerCertificate;
                AdditionalCertificates = ODFSigHandler.Certificates;
                SignatureTime = ODFSigHandler.SignatureTime.ValueUTC;
                if (ODFSigHandler.XAdESProcessor is TElXAdESVerifier)
                    XAdESVerifier = (TElXAdESVerifier)ODFSigHandler.XAdESProcessor;
            }
            else if ((Handler is TElOfficeBinaryUnsupportedSignatureHandler) ||
                     (Handler is TElOfficeOpenXMLUnsupportedSignatureHandler) ||
                     (Handler is TElOpenOfficeUnsupportedSignatureHandler))
                throw new Exception("Unsupported signature handler");
            else if (Handler is TElOfficeBinaryInvalidSignatureHandler)
                throw new Exception("Invalid signature handler: " + ((TElOfficeBinaryInvalidSignatureHandler)Handler).ErrorMessage);
            else if (Handler is TElOfficeOpenXMLInvalidSignatureHandler)
                throw new Exception("Invalid signature handler: " + ((TElOfficeOpenXMLInvalidSignatureHandler)Handler).ErrorMessage);
            else if (Handler is TElOpenOfficeInvalidSignatureHandler)
                throw new Exception("Invalid signature handler: " + ((TElOpenOfficeInvalidSignatureHandler)Handler).ErrorMessage);
            else
                throw new Exception("Unknown signature handler");

            if ((XAdESVerifier != null) && XAdESVerifier.IsEnabled)
            {
                // call XAdESVerifier.Validate() method to validate XAdES info
            }
            else
            {
                // use TElX509CertificateValidator class to validate the signer certificate
            }
        }

        return Result;
    }
}
Delphi:

function ValidateSignature(const SourceFilename : string) : Boolean;
var
  Document : TElOfficeDocument;
  Handler : TElOfficeCustomSignatureHandler;
  XMLSigHandler : TElOfficeOpenXMLBaseSignatureHandler;
  ODFSigHandler : TElOpenOfficeSignatureHandler;
  BinXMLSigHandler : TElOfficeBinaryXMLSignatureHandler;
  BinCryptoAPISigHandler : TElOfficeBinaryCryptoAPISignatureHandler;
  ValidationStatus : TSBOfficeOpenXMLSignatureValidationStatus;
  BinValidationStatus : TSBOfficeBinarySignatureValidationStatus;
  ODFValidationStatus : TSBOpenOfficeSignatureValidationStatus;
  SignerCertificate : TElX509Certificate;
  AdditionalCertificates : TElCustomCertStorage;
  SignatureTime : TDateTime;
  XAdESVerifier : TElXAdESVerifier;
  i : Integer;
begin
  Document := TElOfficeDocument.Create(nil);
  try
    Document.Open(SourceFilename);
    if not Document.IsSigned then
      raise Exception.Create('Document is not signed');

    Result := true;
    for i := 0 to Document.SignatureHandlerCount - 1 do
    begin
      Handler := Document.SignatureHandlers[i];
      XAdESVerifier := nil;
      if Handler is TElOfficeOpenXMLBaseSignatureHandler then
      begin
        XMLSigHandler := TElOfficeOpenXMLBaseSignatureHandler(Handler);
        ValidationStatus := XMLSigHandler.Validate();
        Result := Result and (ValidationStatus = svsValid);

        SignerCertificate := XMLSigHandler.SignerCertificate;
        AdditionalCertificates := XMLSigHandler.Certificates;
        SignatureTime := XMLSigHandler.SignatureTime.ValueUTC;
        if XMLSigHandler.XAdESProcessor is TElXAdESVerifier then
          XAdESVerifier := TElXAdESVerifier(XMLSigHandler.XAdESProcessor);
      end
      else
      if Handler is TElOfficeBinaryCryptoAPISignatureHandler then
      begin
        BinCryptoAPISigHandler := TElOfficeBinaryCryptoAPISignatureHandler(Handler);
        BinValidationStatus := BinCryptoAPISigHandler.Validate();
        Result := Result and (BinValidationStatus = bsvsValid);

        SignerCertificate := BinCryptoAPISigHandler.Certificate;
        AdditionalCertificates := BinCryptoAPISigHandler.IntermediateCertificatesStorage;
        SignatureTime := BinCryptoAPISigHandler.SignTime;
      end
      else
      if Handler is TElOfficeBinaryXMLSignatureHandler then
      begin
        BinXMLSigHandler := TElOfficeBinaryXMLSignatureHandler(Handler);
        BinValidationStatus := BinXMLSigHandler.Validate();
        Result := Result and (BinValidationStatus = bsvsValid);

        SignerCertificate := BinXMLSigHandler.SignerCertificate;
        AdditionalCertificates := BinXMLSigHandler.Certificates;
        SignatureTime := BinXMLSigHandler.SignatureTime.ValueUTC;
        if BinXMLSigHandler.XAdESProcessor is TElXAdESVerifier then
          XAdESVerifier := TElXAdESVerifier(BinXMLSigHandler.XAdESProcessor);
      end
      else
      if Handler is TElOpenOfficeSignatureHandler then
      begin
        ODFSigHandler := TElOpenOfficeSignatureHandler(Handler);
        ODFValidationStatus := ODFSigHandler.Validate();
        Result := Result and (ODFValidationStatus = osvsValid);

        SignerCertificate := ODFSigHandler.SignerCertificate;
        AdditionalCertificates := ODFSigHandler.Certificates;
        SignatureTime := ODFSigHandler.SignatureTime.ValueUTC;
        if ODFSigHandler.XAdESProcessor is TElXAdESVerifier then
          XAdESVerifier := TElXAdESVerifier(ODFSigHandler.XAdESProcessor);
      end
      else
      if (Handler is TElOfficeBinaryUnsupportedSignatureHandler) or
         (Handler is TElOfficeOpenXMLUnsupportedSignatureHandler) or
         (Handler is TElOpenOfficeUnsupportedSignatureHandler) then
        raise Exception.Create('Unsupported signature handler')
      else
      if Handler is TElOfficeBinaryInvalidSignatureHandler then
        raise Exception.Create('Invalid signature handler: ' + TElOfficeBinaryInvalidSignatureHandler(Handler).ErrorMessage)
      else
      if Handler is TElOfficeOpenXMLInvalidSignatureHandler then
        raise Exception.Create('Invalid signature handler: ' + TElOfficeOpenXMLInvalidSignatureHandler(Handler).ErrorMessage)
      else
      if Handler is TElOpenOfficeInvalidSignatureHandler then
        raise Exception.Create('Invalid signature handler: ' + TElOpenOfficeInvalidSignatureHandler(Handler).ErrorMessage)
      else
        raise Exception.Create('Unknown signature handler');

      if Assigned(XAdESVerifier) and XAdESVerifier.IsEnabled then
      begin
        // call XAdESVerifier.Validate() method to validate XAdES info
      end
      else
      begin
        // use TElX509CertificateValidator class to validate the signer certificate
      end;
    end;
  finally
    FreeAndNil(Document);
  end;
end;

How To articles about XML-based signature handlers

Discuss this help topic in SecureBlackbox Forum