Skip to content
Snippets Groups Projects
multikey_sign_and_verify.mjs 3.32 KiB
Newer Older
import jsigs from 'jsonld-signatures';
const {purposes: {AssertionProofPurpose}} = jsigs;
import * as Ed25519Multikey from '@digitalbazaar/ed25519-multikey';
import {DataIntegrityProof} from '@digitalbazaar/data-integrity';
import {cryptosuite as eddsaRdfc2022CryptoSuite} from '@digitalbazaar/eddsa-rdfc-2022-cryptosuite';
import fetch from 'node-fetch';

// Create an in-memory map of documents keyed by their URLs
const documents = new Map();

// Define the addDocumentToLoader function
function addDocumentToLoader({url, document}) {
  documents.set(url, {
    documentUrl: url,
    document,
    contextUrl: null
  });
}

// Define the documentLoader that uses this map
const documentLoader = async url => {
  // If the document is known, return it
  if (documents.has(url)) {
    return {
      contextUrl: null,
      documentUrl: url,
      document: documents.get(url).document
    };
  }

  // Else, you may want to fallback to a default loader or throw an error
  if (url.startsWith('https://www.w3.org/2018/credentials/v1')
    || url.startsWith('https://w3id.org/security/suites/ed25519-2020/v1')
    || url.startsWith('https://w3id.org/security/data-integrity/v2')
    || url.startsWith('https://forge.etsi.org/rep/cim/NGSI-LD/')
    || url.startsWith('https://uri.etsi.org/ngsi-ld')) {
    return {
      contextUrl: null, // this is for a context via a link header
      document: await fetch(url).then(res => res.json()), // this is the actual document that was loaded
      documentUrl: url // this is the actual context URL after redirects
    };
  }

  // If no match is found, throw an error
  throw new Error(`Document loader unable to load URL: ${url}`);
}

// create the JSON-LD document that should be signed
let ngsilddoc = {
  "id": "urn:ngsi-ld:Store:002",
  "type": "Store",
  "address": {
    "type": "Property",
    "value": {
      "streetAddress": ["Tiger Street 4", "al"],
      "addressRegion": "Metropolis",
      "addressLocality": "Cat City",
      "postalCode": "42420"
    }
  },
  "@context": "https://uri.etsi.org/ngsi-ld/primer/store-context.jsonld"
};

// create the keypair to use when signing
const controller = 'https://example.edu/issuers/565049';
const keyPair = await Ed25519Multikey.from({
  '@context': 'https://w3id.org/security/multikey/v1',
  type: 'Multikey',
  controller,
  id: controller + '#z6MkwXG2WjeQnNxSoynSGYU8V9j3QzP3JSqhdmkHc6SaVWoT',
  publicKeyMultibase: 'z6MkwXG2WjeQnNxSoynSGYU8V9j3QzP3JSqhdmkHc6SaVWoT',
  secretKeyMultibase: 'zrv3rbPamVDGvrm7LkYPLWYJ35P9audujKKsWn3x29EUiGwwhdZQd' +
    '1iHhrsmZidtVALBQmhX3j9E5Fvx6Kr29DPt6LH'
});

// export public key and add to document loader
const publicKey = await keyPair.export({publicKey: true, includeContext: true});
addDocumentToLoader({url: publicKey.id, document: publicKey});

// create key's controller document
const controllerDoc = {
  '@context': [
    'https://www.w3.org/ns/did/v1',
    'https://w3id.org/security/multikey/v1'
  ],
  id: controller,
  assertionMethod: [publicKey]
};
addDocumentToLoader({url: controllerDoc.id, document: controllerDoc});

// create suite
const suite = new DataIntegrityProof({
  signer: keyPair.signer(), cryptosuite: eddsaRdfc2022CryptoSuite
});

// create signed credential
const signeddoc = await jsigs.sign(ngsilddoc, {
  suite,
  purpose: new AssertionProofPurpose(),
  documentLoader
});
console.log(JSON.stringify(signeddoc));