UNPKG

@microsoft/useragent-sdk

Version:

SDK for building decentralized identity wallets and enterprise agents.

75 lines (65 loc) 3.25 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import W3cCryptoApiConstants from "../../utilities/W3cCryptoApiConstants"; import base64url from "base64url"; import PrivateKey from "../PrivateKey"; import CryptoFactory from "../../plugin/CryptoFactory"; import { CryptoAlgorithm } from "../../keyStore/IKeyStore"; import KeyTypeFactory, { KeyType } from "../KeyTypeFactory"; import EcPrivateKey from "./EcPrivateKey"; import CryptoError from "../../CryptoError"; import { SubtleCrypto } from 'webcrypto-core'; import JoseConstants from "../../protocols/jose/JoseConstants"; // Create and initialize EC context const BN = require('bn.js'); const elliptic = require('elliptic').ec; const secp256k1 = new elliptic('secp256k1'); const SUPPORTED_CURVES = ['K-256', 'P-256K', 'ed25519']; /** * Class to model EC pairwise keys */ export default class EcPairwiseKey { /** * Generate a pairwise key for the specified algorithms * @param cryptoFactory defining the key store and the used crypto api * @param personaMasterKey Master key for the current selected persona * @param algorithm for the key * @param peerId Id for the peer * @param extractable True if key is exportable */ public static async generate(cryptoFactory: CryptoFactory, personaMasterKey: Buffer, algorithm: EcKeyGenParams, peerId: string): Promise<PrivateKey> { // This method is currently breaking the subtle crypto pattern and needs to be fixed to be platform independent // Get the subtle crypto const crypto: SubtleCrypto = cryptoFactory.getMessageAuthenticationCodeSigners(W3cCryptoApiConstants.Hmac); // Generate the master key const alg: CryptoAlgorithm = { name: W3cCryptoApiConstants.Hmac, hash: W3cCryptoApiConstants.Sha256 }; const signingKey: JsonWebKey = { kty: 'oct', alg: JoseConstants.Hs256, k: base64url.encode(personaMasterKey) }; const key = await crypto.importKey('jwk', signingKey, alg, false, ['sign']); const pairwiseKeySeed = await crypto.sign(alg, key, Buffer.from(peerId)); if (SUPPORTED_CURVES.indexOf(algorithm.namedCurve) === -1) { throw new CryptoError(algorithm, `Curve ${algorithm.namedCurve} is not supported`); } const privateKey = new BN(Buffer.from(pairwiseKeySeed)); const pair = secp256k1.keyPair({ priv: privateKey }); const pubKey = pair.getPublic(); const d = privateKey.toArrayLike(Buffer, 'be', 32); const x = pubKey.x.toArrayLike(Buffer, 'be', 32); const y = pubKey.y.toArrayLike(Buffer, 'be', 32); const pairwise = <EcPrivateKey>{ crv: algorithm.namedCurve, d: base64url.encode(d), x: base64url.encode(x), y: base64url.encode(y), kty:KeyTypeFactory.createViaWebCrypto(algorithm), // Need an algorithm for kid generation - todo kid: '#key1' }; return new EcPrivateKey(pairwise); } }