UNPKG

@dwn-protocol/id-sdk

Version:

SDK for accessing the features and capabilities

110 lines (84 loc) 3.72 kB
import type { IDCrypto } from '../types/iddwn-crypto.js'; import type { BytesKeyPair } from '../types/crypto-key.js'; import { isBytesKeyPair } from '../utils.js'; import { Ed25519 } from '../crypto-primitives/index.js'; import { CryptoKey, BaseEdDsaAlgorithm } from '../algorithms-api/index.js'; export class EdDsaAlgorithm extends BaseEdDsaAlgorithm { public readonly namedCurves = ['Ed25519', 'Ed448']; public async generateKey(options: { algorithm: IDCrypto.EdDsaGenerateKeyOptions, extractable: boolean, keyUsages: IDCrypto.KeyUsage[] }): Promise<IDCrypto.CryptoKeyPair> { const { algorithm, extractable, keyUsages } = options; this.checkGenerateKey({ algorithm, keyUsages }); let keyPair: BytesKeyPair | undefined; let cryptoKeyPair: IDCrypto.CryptoKeyPair; switch (algorithm.namedCurve) { case 'Ed25519': { keyPair = await Ed25519.generateKeyPair(); break; } // Default case not needed because checkGenerateKey() already validates the specified namedCurve is supported. } if (!isBytesKeyPair(keyPair)) { throw new Error('Operation failed to generate key pair.'); } cryptoKeyPair = { privateKey : new CryptoKey(algorithm, extractable, keyPair.privateKey, 'private', this.keyUsages.privateKey), publicKey : new CryptoKey(algorithm, true, keyPair.publicKey, 'public', this.keyUsages.publicKey) }; return cryptoKeyPair; } public async sign(options: { algorithm: IDCrypto.EdDsaOptions, key: IDCrypto.CryptoKey, data: Uint8Array }): Promise<Uint8Array> { const { algorithm, key, data } = options; this.checkAlgorithmOptions({ algorithm }); // The key's algorithm must match the algorithm implementation processing the operation. this.checkKeyAlgorithm({ keyAlgorithmName: key.algorithm.name }); // The key must be a private key. this.checkKeyType({ keyType: key.type, allowedKeyType: 'private' }); // The key must be allowed to be used for sign operations. this.checkKeyUsages({ keyUsages: ['sign'], allowedKeyUsages: key.usages }); let signature: Uint8Array; const keyAlgorithm = key.algorithm as IDCrypto.EdDsaGenerateKeyOptions; // Type guard. switch (keyAlgorithm.namedCurve) { case 'Ed25519': { signature = await Ed25519.sign({ key: key.material, data }); break; } default: throw new TypeError(`Out of range: '${keyAlgorithm.namedCurve}'. Must be one of '${this.namedCurves.join(', ')}'`); } return signature; } public async verify(options: { algorithm: IDCrypto.EdDsaOptions; key: IDCrypto.CryptoKey; signature: Uint8Array; data: Uint8Array; }): Promise<boolean> { const { algorithm, key, signature, data } = options; this.checkAlgorithmOptions({ algorithm }); // The key's algorithm must match the algorithm implementation processing the operation. this.checkKeyAlgorithm({ keyAlgorithmName: key.algorithm.name }); // The key must be a public key. this.checkKeyType({ keyType: key.type, allowedKeyType: 'public' }); // The key must be allowed to be used for verify operations. this.checkKeyUsages({ keyUsages: ['verify'], allowedKeyUsages: key.usages }); let isValid: boolean; const keyAlgorithm = key.algorithm as IDCrypto.EdDsaGenerateKeyOptions; // Type guard. switch (keyAlgorithm.namedCurve) { case 'Ed25519': { isValid = await Ed25519.verify({ key: key.material, signature, data }); break; } default: throw new TypeError(`Out of range: '${keyAlgorithm.namedCurve}'. Must be one of '${this.namedCurves.join(', ')}'`); } return isValid; } }