import jsonld from 'jsonld';
import { JsonWebKey } from '@transmute/json-web-signature';
import defaultDocumentLoader from './document-loader';
import {
EcdsaSecp256k1VerKeyName,
Ed25519VerKeyName,
Sr25519VerKeyName,
EcdsaSecp256k1Signature2019,
Ed25519Signature2018,
Sr25519Signature2020,
Bls12381BBSSignatureDock2022,
Bls12381BBSDockVerKeyName,
Bls12381BBS23DockVerKeyName,
Bls12381BBSSignatureDock2023,
Bls12381PSSignatureDock2023,
Bls12381PSDockVerKeyName,
JsonWebSignature2020,
Ed25519Signature2020,
} from './custom_crypto';
import { Bls12381BDDT16DockVerKeyName, Bls12381BDDT16MacDockName, Ed255192020VerKeyName } from './crypto/constants';
import Bls12381BDDT16MACDock2024 from './crypto/Bls12381BDDT16MACDock2024';
/**
* @typedef {object} KeyDoc The Options to use in the function createUser.
* @property {string} id The key's ID
* @property {any} controller The key's controller ste
* @property {any} type the type of key, Sr25519VerificationKey2020 or Ed25519VerificationKey2018 or EcdsaSecp256k1VerificationKey2019
* @property {object} keypair Keypair is generated by either using polkadot-js's keyring or utils
* @property {object} publicKey The key's public key taken from the keypair
*/
/**
* Helper to get the key doc in a format needed for vc.js.
* @param {string} did - DID in fully qualified form
* @param {object} keypair - Keypair is generated by either using polkadot-js's keyring for Sr25519 and
* Ed25519 or keypair generated with `generateEcdsaSecp256k1Keypair` for curve secp256k1.
* @param {string} type - the type of key, Sr25519VerificationKey2020 or Ed25519VerificationKey2018 or EcdsaSecp256k1VerificationKey2019 or Bls12381G2VerificationKeyDock2022
* @param {string} id - the ID of the key for future resolution
* @returns {KeyDoc}
*/
export function getKeyDoc(did, keypair, type, id) {
return {
id: id || `${did}#keys-1`,
controller: did,
type: type || keypair.verKeyType,
keypair: keypair.keyPair || keypair,
};
}
/**
* Get signature suite from a keyDoc
* @param {object} keyDoc - key document containing `id`, `controller`, `type`, `privateKeyBase58` and `publicKeyBase58`
* @returns {object} - signature suite.
*/
export async function getSuiteFromKeyDoc(keyDoc, useProofValue, options) {
// Check if passing suite directly
if (keyDoc.verificationMethod) {
return keyDoc;
}
let Cls;
let { keypair } = keyDoc;
switch (keyDoc.type) {
case EcdsaSecp256k1VerKeyName:
Cls = EcdsaSecp256k1Signature2019;
break;
case Ed25519VerKeyName:
Cls = Ed25519Signature2018;
break;
case Ed255192020VerKeyName:
Cls = Ed25519Signature2020;
break;
case Sr25519VerKeyName:
Cls = Sr25519Signature2020;
break;
case Bls12381BBSDockVerKeyName:
Cls = Bls12381BBSSignatureDock2022;
break;
case Bls12381BBS23DockVerKeyName:
Cls = Bls12381BBSSignatureDock2023;
break;
case Bls12381PSDockVerKeyName:
Cls = Bls12381PSSignatureDock2023;
break;
case Bls12381BDDT16DockVerKeyName:
Cls = Bls12381BDDT16MACDock2024;
break;
case 'JsonWebKey2020':
Cls = JsonWebSignature2020;
if (!keypair) {
keypair = await JsonWebKey.from(keyDoc, options);
}
break;
default:
throw new Error(`Unknown key type ${keyDoc.type}.`);
}
return new Cls({
...keyDoc,
verificationMethod: keyDoc.id,
useProofValue,
keyDoc,
keypair,
});
}
/**
* Helper method to ensure credential is valid according to the context
* @param credential
*/
export async function expandJSONLD(credential, options = {}) {
if (options.documentLoader && options.resolver) {
throw new Error(
'Passing resolver and documentLoader results in resolver being ignored, please re-factor.',
);
}
const expanded = await jsonld.expand(credential, {
...options,
documentLoader:
options.documentLoader || defaultDocumentLoader(options.resolver),
});
return expanded[0];
}
export function potentialToArray(a) {
/* eslint-disable no-nested-ternary */
return a ? (Array.isArray(a) ? a : [a]) : [];
}
export function getKeyFromDIDDocument(didDocument, didUrl) {
// Ensure not already a key doc
if (
didDocument.publicKeyBase58
|| didDocument.publicKeyMultibase
|| didDocument.publicKeyJwk
|| (didDocument.publicKey && !Array.isArray(didDocument.publicKey))
) {
return didDocument;
}
const possibleKeys = [
...potentialToArray(didDocument.verificationMethod),
...potentialToArray(didDocument.keyAgreement),
...potentialToArray(didDocument.publicKey),
];
return possibleKeys.filter((key) => key.id === didUrl)[0];
}
/**
* For KVAC, public key is not present so the holder assumes that the given credential is valid.
* Secondly, these credentials are never shared as it is with the verifier so this function returns true if the credential is
* a KVAC, else returns undefined.
* @param credential
* @returns {object | undefined}
*/
export function processIfKvac(credential) {
const { proof } = credential;
if (proof === undefined || proof.type === undefined) {
throw new Error(`Credential should have a non-null type field but found ${proof.type}`);
}
if (proof.type === Bls12381BDDT16MacDockName) {
return {
results: [{
verified: true, proof, verificationMethod: {}, purposeResult: {},
}],
verified: true,
};
}
return undefined;
}