@microsoft/useragent-sdk
Version:
SDK for building decentralized identity wallets and enterprise agents.
94 lines (81 loc) • 3.77 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 CryptoFactory from "../plugin/CryptoFactory";
import { CryptoAlgorithm } from "../keyStore/IKeyStore";
import KeyTypeFactory, { KeyType } from "./KeyTypeFactory";
import W3cCryptoApiConstants from "../utilities/W3cCryptoApiConstants";
import EcPairwiseKey from "./ec/EcPairwiseKey";
import CryptoError from "../CryptoError";
import RsaPairwiseKey from "./rsa/RsaPairwiseKey";
import PrivateKey from "./PrivateKey";
import { SubtleCrypto } from 'webcrypto-core';
import JoseConstants from "../protocols/jose/JoseConstants";
import OctKey from "./Oct/OctKey";
import IKeyContainer from "./IKeyContainer";
/**
* Class to model pairwise keys
*/
export default class PairwiseKey {
/**
* Get or set the crypto factory to use, containing the crypto suite and the key store.
*/
private cryptoFactory: CryptoFactory;
// Set of master keys for the different persona's
private masterKeys: Map<string, Buffer> = new Map<string, Buffer>();
/**
* Create an instance of @class PairwiseKey.
* @param cryptoFactory The crypto factory object.
*/
public constructor (cryptoFactory: CryptoFactory) {
this.cryptoFactory = cryptoFactory;
}
/**
* Generate a pairwise key for the specified algorithms
* @param algorithm for the key
* @param seedReference Reference to the seed
* @param personaId Id for the persona
* @param peerId Id for the peer
*/
public async generatePairwiseKey(algorithm: EcKeyGenParams | RsaHashedKeyGenParams, seedReference: string, personaId: string, peerId: string): Promise<PrivateKey> {
const personaMasterKey: Buffer = await this.generatePersonaMasterKey(seedReference, personaId);
const keyType = KeyTypeFactory.createViaWebCrypto(algorithm);
switch (keyType) {
case KeyType.EC:
case KeyType.OKP:
return EcPairwiseKey.generate(this.cryptoFactory, personaMasterKey, <EcKeyGenParams>algorithm, peerId);
case KeyType.RSA:
return RsaPairwiseKey.generate(this.cryptoFactory, personaMasterKey, <RsaHashedKeyGenParams>algorithm, peerId);
default:
throw new CryptoError(algorithm, `Pairwise key for type '${keyType}' is not supported.`);
}
}
/**
* Generate a pairwise master key.
* @param seedReference The master seed for generating pairwise keys
* @param personaId The owner DID
*/
private async generatePersonaMasterKey (seedReference: string, personaId: string): Promise<Buffer> {
let mk: Buffer | undefined = this.masterKeys.get(personaId);
if (mk) {
return mk;
}
// Get the seed
const jwk = <OctKey>(<IKeyContainer> await this.cryptoFactory.keyStore.get(seedReference, false)).getKey();
// Get the subtle crypto
const crypto: SubtleCrypto = this.cryptoFactory.getMessageAuthenticationCodeSigners(W3cCryptoApiConstants.Hmac);
// Generate the master key
const alg: CryptoAlgorithm = { name: W3cCryptoApiConstants.Hmac, hash: W3cCryptoApiConstants.Sha512 };
const masterJwk = {
kty: 'oct',
alg: JoseConstants.Hs512,
k: jwk.k
};
let key = await crypto.importKey('jwk', masterJwk, alg, false, ['sign']);
const masterKey = await crypto.sign(alg, key, Buffer.from(personaId));
mk = Buffer.from(masterKey);
this.masterKeys.set(personaId, mk);
return mk;
}
}