Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Support SigPolicyId#57

Merged
microshine merged 1 commit into
PeculiarVentures:masterfrom
brainbeanapps:support_SigPolicyId
Nov 24, 2017
Merged

Support SigPolicyId#57
microshine merged 1 commit into
PeculiarVentures:masterfrom
brainbeanapps:support_SigPolicyId

Conversation

@alexey-pelykh

Copy link
Copy Markdown
Contributor

No description provided.

@alexey-pelykh

Copy link
Copy Markdown
Contributor Author

@microshine as requested

@microshine
microshine merged commit 47687c9 into PeculiarVentures:master Nov 24, 2017
@microshine

microshine commented Nov 24, 2017

Copy link
Copy Markdown
Contributor

@alexey-pelykh I'll publish it today. I have to fix tslint issues and make some tests. I'll notice you when it's done

@microshine

microshine commented Nov 24, 2017

Copy link
Copy Markdown
Contributor

@alexey-pelykh I published xmldsigjs and xadesjs

Here is my test script

TypeScript

import * as fs from "fs";
import * as xmlcore from "xml-core";
import * as xmldsig from "xmldsigjs";
import * as xades from "xadesjs";
const { XMLSerializer } = require("xmldom-alpha");
const pkijs = require("pkijs");
const asn1js = require("asn1js");
const WebCrypto = require("node-webcrypto-ossl");
const crypto = new WebCrypto() as Crypto;

// Set crypto engine
xmldsig.Application.setEngine("OpenSSL", crypto);
pkijs.setEngine("OpenSSL", crypto, new pkijs.CryptoEngine({ name: "OpenSSL", crypto, subtle: crypto.subtle }));

async function main() {
    await sign();
}

main()
    .catch((err) => console.error(err));

async function verify() {
    const ping = fs.readFileSync("ping.xml", "utf8");
    const signatures1 = fs.readFileSync("test.xml", "utf8");

    const signedDocument = xades.Parse(signatures1);
    const pingDocument = xades.Parse(ping);

    const xmlSignature = signedDocument.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature");
    const signedXml = new xmldsig.SignedXml(pingDocument);
    signedXml.LoadXml(xmlSignature[0]);
    const res = await signedXml.Verify();
    console.log((res ? "Valid" : "Invalid") + " signature");
}

async function sign() {
    const ping = fs.readFileSync("ping.xml", "utf8");
    const alg = {
        name: "RSASSA-PKCS1-v1_5",
        hash: "SHA-256",
        publicExponent: new Uint8Array([1, 0, 1]),
        modulusLength: 2048,
    };


    // parse xml
    const asicDocument = xades.Parse(`<asic:XAdESSignatures xmlns:asic="http://uri.etsi.org/02918/v1.2.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"></asic:XAdESSignatures>`);
    const pingDocument = xades.Parse(ping);

    // generate key
    const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]);
    const cert = await GenerateCertificate(keys);
    const certDer = Buffer.from(cert.toSchema().toBER());

    await writePublicKey(keys);
    fs.writeFileSync("cert.der", certDer, { encoding: "binary" });

    let signature = new xades.SignedXml();
    // set parent for xml signature
    signature.Parent = asicDocument.firstChild as Element;

    // Signing document
    await signature.Sign(
        alg,
        keys.privateKey,
        pingDocument,
        {
            keyValue: keys.publicKey,
            x509: [certDer.toString("base64")],
            references: [
                { hash: "SHA-256", uri: "ping.xml" },
            ],
            signingCertificate: certDer.toString("base64"),
        });

    asicDocument.firstChild!.appendChild(signature.GetXml()!);

    // console.log(await signature.Verify());

    // serialize xml to string
    const signedXml = new XMLSerializer().serializeToString(asicDocument);
    fs.writeFileSync("test.xml", signedXml);
    console.log(signedXml);
}
async function writePublicKey(keys: CryptoKeyPair) {
    const raw = await crypto.subtle.exportKey("spki", keys.publicKey);
    fs.writeFileSync("pubKey.der", Buffer.from(raw), { encoding: "binary" });
}

async function GenerateCertificate(keyPair: CryptoKeyPair) {
    const certificate = new pkijs.Certificate();

    // region Put a static values
    certificate.version = 2;
    const serialNumber = crypto.getRandomValues(new Uint8Array(10));
    certificate.serialNumber = new asn1js.Integer();
    certificate.serialNumber.valueBlock.valueHex = serialNumber.buffer;

    const commonName = new pkijs.AttributeTypeAndValue({
        type: "2.5.4.3", // Common name
        value: new asn1js.PrintableString({ value: "Test certificate" }),
    });

    certificate.issuer.typesAndValues.push(commonName);
    certificate.subject.typesAndValues.push(commonName);

    // Valid period is 1 year
    certificate.notBefore.value = new Date(); // current date
    const notAfter = new Date();
    notAfter.setFullYear(notAfter.getFullYear() + 1);
    certificate.notAfter.value = notAfter;

    certificate.extensions = []; // Extensions are not a part of certificate by default, it's an optional array

    // Basic constraints
    const basicConstraints = new pkijs.BasicConstraints({
        cA: true,
        pathLenConstraint: 2,
    });
    certificate.extensions.push(new pkijs.Extension({
        extnID: "2.5.29.19",
        critical: false,
        extnValue: basicConstraints.toSchema().toBER(false),
        parsedValue: basicConstraints,
    }));

    await certificate.subjectPublicKeyInfo.importKey(keyPair.publicKey);
    await certificate.sign(keyPair.privateKey, "SHA-256");

    return certificate;
}

Output

> tsc && node out && xmlsec1 --verify test.xml

<asic:XAdESSignatures xmlns:asic="http://uri.etsi.org/02918/v1.2.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"><ds:Signature Id="id-d1e4af8223e3"><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="ping.xml"><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>z3ByVkSbcyGXyYX1lnT+WW+FKRWZj/ReR2gX6Ade5Zc=</ds:DigestValue></ds:Reference><ds:Reference URI="#xades-id-d1e4af8223e3" Type="http://uri.etsi.org/01903#SignedProperties"><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>6T2zSMlpyR6c8MNNctST47cniDetHfJOW45AZkQwPC4=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>EiES0p4ZXkqy49R1mEtN0JrR3SeYjDK+eXNldTUtWuIOwPELrU4KRcjL/P+eoZm9LtpfJ1d1P4fr86kd/VU420sfFTjaoQhvhu+cU2czY+dThR0SBEJIgnntmEvUr8UCbwbugxwOGHBw9OS26wx0bvq+gL4vaf4kVDjcOy6vTmPo4neByiiqt5Dh2j8/OeeGDXEVuzipUy778Xz/droGVqTq2IupT6Rz5iYk9vjv01Z0wufQEcTdfP3IGuguFoMUogkEqeYEGutM37NVrrMDEyDMtGDc2MZe0NJL6iKZHS+YgC0UZomCsluDwcFNzWd2si0XH0vsGlIuBuuc4xJisw==</ds:SignatureValue><ds:KeyInfo><ds:KeyValue><ds:RSAKeyValue><ds:Modulus>rwr06tnTGI1jIxJvyRCGHHTArnPc/0U1f7Ie7RP+LvfU84RicU+VTSkVDa2RQ8WTS01Th8rNQwqH06Wx6MKf2GYByrrCbYDG7TInv/XLNRu+FCYCaREdB9RheRT0G39Q6QugZuwbClKEazzgiPZgg7OZPVqPyCX+jXxcwde+F0fIakVFkAgm8lhcz59rpH2X7VHTgZihvmGmTqO+Wtq71QO0moZM6Fhq2bWVQj3e/oRfKVSRhlUTmNNDR+V7BEVNTHLcsp7SGJr0ROOWIMZiglK2nrWz6QG0UFOxtNs5TMBhBiEA2LSkcVxGUhM/rNVCJgje/WzZQK/YUmJlMpKS7Q==</ds:Modulus><ds:Exponent>AQAB</ds:Exponent></ds:RSAKeyValue></ds:KeyValue><ds:X509Data><ds:X509Certificate>MIICyTCCAbOgAwIBAgIKwLdiufKLYL499TALBgkqhkiG9w0BAQswGzEZMBcGA1UEAxMQVGVzdCBjZXJ0aWZpY2F0ZTAeFw0xNzExMjQxMzQ2NDlaFw0xODExMjQxMzQ2NDlaMBsxGTAXBgNVBAMTEFRlc3QgY2VydGlmaWNhdGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvCvTq2dMYjWMjEm/JEIYcdMCuc9z/RTV/sh7tE/4u99TzhGJxT5VNKRUNrZFDxZNLTVOHys1DCofTpbHowp/YZgHKusJtgMbtMie/9cs1G74UJgJpER0H1GF5FPQbf1DpC6Bm7BsKUoRrPOCI9mCDs5k9Wo/IJf6NfFzB174XR8hqRUWQCCbyWFzPn2ukfZftUdOBmKG+YaZOo75a2rvVA7SahkzoWGrZtZVCPd7+hF8pVJGGVROY00NH5XsERU1MctyyntIYmvRE45YgxmKCUraetbPpAbRQU7G02zlMwGEGIQDYtKRxXEZSEz+s1UImCN79bNlAr9hSYmUykpLtAgMBAAGjEzARMA8GA1UdEwQIMAYBAf8CAQIwCwYJKoZIhvcNAQELA4IBAQB6mJ0obDDkvhJGRyRmuVbEVW2aB2SdOeh2j7w/C0qaKbHOII720iKDdJ2rvMKAytRpJt8iEnlgvzLoC77qybxSLALDaqFQXcNxR2dQod92lE6i+79VKDVJNN3J/pcAZLBHPm+L5vYClftkIilddLwhK7XY0FNcXQ8C0kvHvgUi6zuS9RnEAxH/iRfk+A8dR+abWkDJH1IJQFq3AQmvPyVkUmU/GtBUUYyxhG8mJx4vjx57BDfY+30RChmXi1hSJk3+Af2+gf4WUuBu+aZJm6U57eqqpQVarjqL2B0HbIhTceJF+PuywvDuXlonTOeeTeYrUhCevfWk7MmPGWePruoT</ds:X509Certificate></ds:X509Data></ds:KeyInfo><ds:Object><xades:QualifyingProperties Target="#id-d1e4af8223e3"><xades:SignedProperties Id="xades-id-d1e4af8223e3"><xades:SignedSignatureProperties><xades:SigningTime>2017-11-24T13:46:49.956Z</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>fKywgzapm+Q9ySUKpG5MXbp786Vez2RQu7+YXHOvCrU=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>CN=Test certificate</ds:X509IssuerName><ds:X509SerialNumber>-298848586754401599865355</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyImplied/></xades:SignaturePolicyIdentifier></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object></ds:Signature></asic:XAdESSignatures>
OK
SignedInfo References (ok/all): 2/2
Manifests References (ok/all): 0/0

@alexey-pelykh
alexey-pelykh deleted the support_SigPolicyId branch November 24, 2017 14:21
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants