<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">

<!-- Babel Polyfill -->
<script defer src="https://fortifyapp.com/external/babel-polyfill/6.26.0/polyfill.min.js"></script>

<!-- Components -->
<script defer type="module" src="https://fortifyapp.com/external/webcomponent/build/peculiar.esm.js"></script>
<script defer nomodule src="https://fortifyapp.com/external/webcomponent/build/peculiar.js"></script>
<link rel="stylesheet" href="https://fortifyapp.com/external/webcomponent/build/peculiar.css">

<!-- Crypto -->
<script defer src="https://fortifyapp.com/external/pvtsutils/pvtsutils.js"></script>
<script defer src="https://fortifyapp.com/external/asn1js/asn1.min.js"></script>
<script defer src="https://fortifyapp.com/external/pkijs/pki.min.js"></script>

<!-- XAdES -->
<script defer src="https://unpkg.com/xadesjs@2.0.18/build/xades.min.js"></script>

<style>
  body {
    height: 100vh;
    background: #6D7D87;
  }
  
  section {
    max-width: 660px;
    width: calc(100% - 20px);
    margin: 20px auto;
  }
  
  textarea {
    width: 100%;
  }
</style>

<section>
  <br>
  <textarea id="output" cols="60" rows="10"></textarea>

  <p>
    Verify XML signed document online on
    <a href="https://www.aleksey.com/xmlsec/xmldsig-verifier.html"
       >www.aleksey.com</a
      >
  </p>
</section>

<script>
  function formatPEM (raw, tag) {
    var pemString = pvtsutils.Convert.ToBase64(raw);
    var stringLength = pemString.length;
    var resultString = "";

    for (var i = 0, count = 0; i < stringLength; i++, count++) {
      if (count > 63) {
        resultString = resultString + '\n';
        count = 0;
      }

      resultString = resultString + pemString[i];
    }

    return '-----BEGIN ' + tag.toUpperCase() + '-----\n' + resultString + '\n-----END ' + tag.toUpperCase() + '-----\n';
  }

  async function continueHandler(event) {
    try {
      var demoData = `<xml>
        <text>Demo message</text>
      </xml>`;
      var provider = await event.detail.server.getCrypto(event.detail.providerId);

      XAdES.Application.setEngine("Fortify", provider);
      
      var xml = XAdES.Parse(demoData);
      var signedXml = new XAdES.SignedXml();

      var cert = await provider.certStorage.getItem(event.detail.certificateId);
      var privateKey = await provider.keyStorage.getItem(event.detail.privateKeyId);
      var certRawData = await provider.certStorage.exportCert('raw', cert);
      var x509 = pvtsutils.Convert.ToBase64(certRawData);
      
      var signature = await signedXml.Sign(
        // Signing document
        cert.publicKey.algorithm.toAlgorithm(),
        privateKey, // key
        xml, // document
        {
          // options
          keyValue: cert.publicKey,
          x509: [x509],
          references: [{ hash: "SHA-1", transforms: ["enveloped"] }],
          signingCertificate: x509,
        },
      );
      
      xml.documentElement.appendChild(signature.GetXml());
      
      output.innerHTML = new XMLSerializer().serializeToString(xml);
    } catch (error) {
      alert('Failed to sign XML');
      console.error(error);
    }
  }
</script>
<script>
  var el = document.createElement('peculiar-fortify-certificates');
  // el.language = 'ru';
  el.debug = true;
  el.filters = {
    //   onlySmartcards: false,
    //   expired: false,
    onlyWithPrivateKey: true,
    //   subjectDNMatch: 'apple',
    //   subjectDNMatch: new RegExp(/apple/),
    //   issuerDNMatch: 'demo',
    //   issuerDNMatch: new RegExp(/demo/),
    //   providerNameMatch: 'MacOS',
    //   providerNameMatch: new RegExp(/MacOS/),
    //   keyUsage: ['digitalSignature'],
    //   certificateIdMatch: 'test',
  };

  el.addEventListener('cancel', function() {
    alert('"cancel" callback');
  });

  el.addEventListener('continue', continueHandler);
  
  document.getElementsByTagName('section')[0].prepend(el);
</script>
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.