@digitalcredentials/keypair
Version:
Cryptographic key pair data model in Javascript/Typescript, for Node.js, browsers, and React Native. Useful for Verifiable Credentials, DIDs (Decentralized Identifiers), and other uses of Data Integrity.
126 lines (125 loc) • 5.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeyPair = void 0;
class KeyPair {
/**
* Creates a public/private key pair instance. This is an abstract base class,
* actual key material and suite-specific methods are handled in the subclass.
*
* To generate or import a key pair, use the `cryptoLd` instance.
*
* @see CryptoLD.js
*
* @param {object} options - The options to use.
* @param {string} options.id - The key id, typically composed of controller
* URL and key fingerprint as hash fragment.
* @param {string} options.controller - DID/URL of the person/entity
* controlling this key.
* @param {string} [options.revoked] - Timestamp of when the key has been
* revoked, in RFC3339 format. If not present, the key itself is
* considered not revoked. (Note that this mechanism is slightly different
* than DID Document key revocation, where a DID controller can revoke a
* key from that DID by removing it from the DID Document.)
*/
constructor({ id, controller, revoked } = {}) {
this.id = id;
this.type = ''; // type must be set by subclasses
this.controller = controller;
this.revoked = revoked;
}
/**
* Generates a new public/private key pair instance.
* Note that this method is not typically called directly by client code,
* but instead is used through a `cryptoLd` instance.
*
* @param {object} options - Suite-specific options for the KeyPair. For
* common options, see the `LDKeyPair.constructor()` docstring.
*
* @returns {Promise<KeyPair>} An LDKeyPair instance.
*/
static async generate(options = {}) {
throw new Error('Abstract method, must be implemented in subclass.');
}
/**
* Imports a key pair instance from a provided externally fetched key
* document (fetched via a secure JSON-LD `documentLoader` or via
* `cryptoLd.fromKeyId()`), optionally checking it for revocation and required
* context.
*
* @param {object} options - Options hashmap.
* @param {string} options.document - Externally fetched key document.
* @param {boolean} [options.checkContext=true] - Whether to check that the
* fetched key document contains the context required by the key's crypto
* suite.
* @param {boolean} [options.checkRevoked=true] - Whether to check the key
* object for the presence of the `revoked` timestamp.
*
* @returns {Promise<KeyPair>} Resolves with the resulting key pair
* instance.
*/
static async fromKeyDocument({ document, checkContext = true, checkRevoked = true }) {
if (checkContext) {
const fetchedDocContexts = Array.isArray(document['@context'])
? document['@context']
: [document['@context']];
if (!document['@context'] ||
!fetchedDocContexts.includes(this.SUITE_CONTEXT)) {
throw new Error('Key document does not contain required context "' +
this.SUITE_CONTEXT +
'".');
}
}
if (checkRevoked && document.revoked) {
throw new Error(`Key has been revoked since: "${document.revoked}".`);
}
return this.from(document);
}
/**
* Generates a KeyPair from some options.
*
* @param {object} options - Will generate a key pair in multiple different
* formats.
* @example
* > const options = {
* type: 'Ed25519VerificationKey2020'
* };
* > const edKeyPair = await LDKeyPair.from(options);
*
* @returns {Promise<KeyPair>} A LDKeyPair.
* @throws Unsupported Key Type.
*/
static async from(options) {
throw new Error('Abstract method from() must be implemented in subclass.');
}
/**
* Exports the serialized representation of the KeyPair
* and other information that json-ld Signatures can use to form a proof.
*
* NOTE: Subclasses MUST override this method (and add the exporting of
* their public and private key material).
*
* @param {object} [options={}] - Options hashmap.
* @param {boolean} [options.publicKey] - Export public key material?
* @param {boolean} [options.privateKey] - Export private key material?
*
* @returns {object} A public key object
* information used in verification methods by signatures.
*/
export({ publicKey = false, privateKey = false, includeContext = false } = {}) {
if (!publicKey && !privateKey) {
throw new Error('Export requires specifying either "publicKey" or "privateKey".');
}
const key = {
id: this.id,
type: this.type,
controller: this.controller
};
if (this.revoked) {
key.revoked = this.revoked;
}
return key;
}
}
exports.KeyPair = KeyPair;
// Implementers must override this in subclasses
KeyPair.SUITE_CONTEXT = 'INVALID KeyPair CONTEXT';