PeculiarVentures/xadesjs

XAdEs-T example

GLR21 opened this issue · 3 comments

GLR21 commented

Hi, I would like to ask if is there any example I could follow to generate a XAdEs-T signature? I already have the certificates, keys and timestamp, I just haven't found any example I could use with xadesjs.

Best regards,
Gabriel Lange Ramos.

Looking at

xadesjs/src/signed_xml.ts

Lines 98 to 103 in 4e13cfe

get UnsignedProperties(): XAdES.UnsignedProperties {
if (!this.Properties) {
throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, "Properties is empty");
}
return this.Properties.UnsignedProperties;
}

The property you want is SignatureTimeStamp

* <xsd:element name="UnsignedSignatureProperties" type="UnsignedSignaturePropertiesType"/>
* <xsd:complexType name="UnsignedSignaturePropertiesType">
* <xsd:choice maxOccurs="unbounded">
* <xsd:element name="CounterSignature" type="CounterSignatureType"/>
* <xsd:element name="SignatureTimeStamp" type="XAdESTimeStampType"/>
* <xsd:element name="CompleteCertificateRefs" type="CompleteCertificateRefsType"/>
* <xsd:element name="CompleteRevocationRefs" type="CompleteRevocationRefsType"/>
* <xsd:element name="AttributeCertificateRefs" type="CompleteCertificateRefsType"/>
* <xsd:element name="AttributeRevocationRefs" type="CompleteRevocationRefsType"/>
* <xsd:element name="SigAndRefsTimeStamp" type="XAdESTimeStampType"/>
* <xsd:element name="RefsOnlyTimeStamp" type="XAdESTimeStampType"/>
* <xsd:element name="CertificateValues" type="CertificateValuesType"/>
* <xsd:element name="RevocationValues" type="RevocationValuesType"/>
* <xsd:element name="AttrAuthoritiesCertValues" type="CertificateValuesType"/>
* <xsd:element name="AttributeRevocationValues" type="RevocationValuesType"/>
* <xsd:element name="ArchiveTimeStamp" type="XAdESTimeStampType"/>
* <xsd:any namespace="##other"/>
* </xsd:choice>
* <xsd:attribute name="Id" type="xsd:ID" use="optional"/>
* </xsd:complexType>

I think you might want something like

* <xsd:element name="EncapsulatedTimeStamp" type="EncapsulatedPKIDataType"/>

Taking this into account, I think you want to modify the Sign call from the README.md to be,

import * as XAdES from 'xadesjs';

...

  var signedXml = new XAdES.SignedXml();
  var ts = new XAdES.xml.SignatureTimeStamp();
  ts.EncapsulatedTimeStamp.Add(new XAdES.xml.EncapsulatedTimeStamp())
  signedXml.Properties.UnsignedProperties.UnsignedSignatureProperties.Add(ts)
  console.log(signedXml.Properties.UnsignedProperties.UnsignedSignatureProperties);

I imagine you have to add something to the EncapsulatedTimeStamp, but I haven't figured that out yet. Please update if you figure that part out.

I think you setup the EncapsultedTimeStamp by setting the value element. Parent class below,

export class EncapsulatedPKIData extends XadesObject {
@XmlAttribute({
localName: XmlXades.AttributeNames.Id,
defaultValue: "",
})
public Id: string;
@XmlAttribute({
localName: XmlXades.AttributeNames.Encoding,
defaultValue: null,
converter: XmlEncodingConverter,
})
public Encoding: EncodingType;
@XmlContent({
required: true,
converter: XmlBase64Converter,
})
public Value: Uint8Array;
}

Here is a simple example of XAdES-T creation.

TypeScript

const crypto = new Crypto();
const alg: globalThis.RsaHashedKeyGenParams = {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256",
    publicExponent: new Uint8Array([1, 0, 1]),
    modulusLength: 2048,
};
const dataRaw = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
const tsRaw = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);

// Generate RSA keypair
const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]) as Required<CryptoKeyPair>;

// Create self-signed certificate
const cert = await x509.X509CertificateGenerator.createSelfSigned({
    name: "CN=Test",
    keys,
    serialNumber: "010203",
    signingAlgorithm: alg,
    notBefore: new Date("2022-01-18"),
    notAfter: new Date("2022-01-19"),
}, crypto);

XAdES.Application.setEngine("NodeJS", crypto);

// Create XAdES-T signature
const signedXml = new XAdES.SignedXml();
const ts = new XAdES.xml.SignatureTimeStamp();
const ets = new XAdES.xml.EncapsulatedTimeStamp();
ets.Encoding = "ber";
ets.Value = tsRaw;
ts.EncapsulatedTimeStamp.Add(ets);
signedXml.UnsignedProperties.UnsignedSignatureProperties.Add(ts);

const signingCertString = cert.toString("base64");
await signedXml.Sign(alg, keys.privateKey, dataRaw, {
    keyValue: keys.publicKey,
    x509: [signingCertString],
    references: [
        {
            hash: "SHA-256",
            uri: "some.txt",
        }
    ],
    signingCertificate: signingCertString,
});

console.log(signedXml.toString());

Output (formatted)

<ds:Signature Id="id-0d84c844c447"
  xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
    <ds:Reference URI="some.txt">
      <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <ds:DigestValue>monGjExeKLjEpVZ2c9Ri//UV20YRb5kAYk0JxHT1k/s=</ds:DigestValue>
    </ds:Reference>
    <ds:Reference URI="#xades-id-0d84c844c447" Type="http://uri.etsi.org/01903#SignedProperties">
      <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <ds:DigestValue>GDeoqLDJBs5CkKJMTkvX41TuRob98fxji8cAFbfcDxQ=</ds:DigestValue>
    </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue>e1Kwra0HwQFTnZ+vRyJaGgPedJlhvf1pn6s4jKMMW6zGYJn3Sz0xmW+bso7bXSkMw1DsmOaObRwVKb01EZrufTgw8cYFQbe7Ks6Q3WKx07+URrdQVBqER12iXaAFx5VsfARaXAxzK4jk1RtV4CJTufF58B2cY3At4VnDAZlLvO3rfhqsaWkPF3foBSN4ompzqPk/emQVb/WYL5jTJhLmM6eHqEGQbDg2I1M2Wzq1byA+ks1FBXww3eRVLinQIbZtoLBCTi9XZ6VxHsKxbeM7yLyG87TXuSDNGz2nDLLhfWM7D78fGHK+n9wepH2ly3+ygl6lrbiXS3M69Pqu11EkCA==</ds:SignatureValue>
  <ds:KeyInfo>
    <ds:KeyValue>
      <ds:RSAKeyValue>
        <ds:Modulus>3EpI4qi0J3v5OXBHh8e5AEDd7y71lT9r3RwR+ApON9W5+jGsuea9lCQjU9SGIYKwCeUs6x/TIsTxsbYsnIFxX7ZX4ag6xIfC9rPscnTHfaCxpZ1nbz1hkUqF6MilNVK27EwIIyu0EHmIaJdKyUSOKXhEBJDUWO8M345Dn49ySspm1FpHD+Q4sio0QSfW+btqby1+FCVERund+It9xX4IfQWr8S2PsnnGLRzPYL5s1dRL/04sPg2WaAN8JzmoyeO+1uGxNYYjB227L6NsX6JAgDFcyEAKCsL5hpb3smC/XOYGVmTvvL355tFB8SXdx838AFmziUWhLDpvJjWZeMoTmQ==</ds:Modulus>
        <ds:Exponent>AQAB</ds:Exponent>
      </ds:RSAKeyValue>
    </ds:KeyValue>
    <ds:X509Data>
      <ds:X509Certificate>MIICnTCCAYWgAwIBAgIDAQIDMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNVBAMTBFRlc3QwHhcNMjIwMTE4MDAwMDAwWhcNMjIwMTE5MDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3EpI4qi0J3v5OXBHh8e5AEDd7y71lT9r3RwR+ApON9W5+jGsuea9lCQjU9SGIYKwCeUs6x/TIsTxsbYsnIFxX7ZX4ag6xIfC9rPscnTHfaCxpZ1nbz1hkUqF6MilNVK27EwIIyu0EHmIaJdKyUSOKXhEBJDUWO8M345Dn49ySspm1FpHD+Q4sio0QSfW+btqby1+FCVERund+It9xX4IfQWr8S2PsnnGLRzPYL5s1dRL/04sPg2WaAN8JzmoyeO+1uGxNYYjB227L6NsX6JAgDFcyEAKCsL5hpb3smC/XOYGVmTvvL355tFB8SXdx838AFmziUWhLDpvJjWZeMoTmQIDAQABowIwADANBgkqhkiG9w0BAQsFAAOCAQEATel2jf8g9s+HLq5vPRUMNfI8zcSokYPzNQveIZ2NJAOwh3vXhH3MiXBQ4kpsOUaUOCB6KxZ6xvpeAc/LkI2rjxetbGfyRfN5GCQ5kHIL7ArGSNsZjRlxjy/JeiXRDHIPQ5S5IKGVy+FEkenmD6Sn7jgD1FpjVw3CV1zUc+5QT5MMX0150sKCkGd1KAMsYrFdY6FGQ2JbF7jk1ib/LF+HwnZWg5VJBpAwlPAq/EOf/iNhsXtbA+60jhnFJZE/iUjB4ha/IO+4kBbhjEVA4nuzlK9Dox0IQBc/7MtHo9Ysf2BOshAGC35jvRj10qoRvOa6C/HyziL57pdOoLI3SIQAFQ==</ds:X509Certificate>
    </ds:X509Data>
  </ds:KeyInfo>
  <ds:Object>
    <xades:QualifyingProperties Target="#id-0d84c844c447"
      xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">
      <xades:SignedProperties Id="xades-id-0d84c844c447">
        <xades:SignedSignatureProperties>
          <xades:SigningTime>2022-01-18T15:33:10.634Z</xades:SigningTime>
          <xades:SigningCertificate>
            <xades:Cert>
              <xades:CertDigest>
                <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <ds:DigestValue>9uR1h3fw2wxkwXXcM/FRr4BCpgppjph0l51JBcYwFEg=</ds:DigestValue>
              </xades:CertDigest>
              <xades:IssuerSerial>
                <ds:X509IssuerName>CN=Test</ds:X509IssuerName>
                <ds:X509SerialNumber>66051</ds:X509SerialNumber>
              </xades:IssuerSerial>
            </xades:Cert>
          </xades:SigningCertificate>
        </xades:SignedSignatureProperties>
      </xades:SignedProperties>
      <xades:UnsignedProperties>
        <xades:UnsignedSignatureProperties>
          <xades:SignatureTimeStamp>
            <xades:EncapsulatedTimeStamp Encoding="http://uri.etsi.org/01903/v1.2.2#BER">AQIDBAUGBwgJAA==</xades:EncapsulatedTimeStamp>
          </xades:SignatureTimeStamp>
        </xades:UnsignedSignatureProperties>
      </xades:UnsignedProperties>
    </xades:QualifyingProperties>
  </ds:Object>
</ds:Signature>