@microsoft/useragent-sdk
Version:
SDK for building decentralized identity wallets and enterprise agents.
75 lines (65 loc) • 3.25 kB
text/typescript
/*---------------------------------------------------------------------------------------------
* 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);
}
}