@microsoft/useragent-sdk
Version:
SDK for building decentralized identity wallets and enterprise agents.
134 lines (109 loc) • 4.68 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 Identifier from '../../../Identifier';
import IResolver from '../../../resolvers/IResolver';
import JwsToken from '../jose/jws/JwsToken';
import CryptoFactory from '../../plugin/CryptoFactory';
import UserAgentOptions from '../../../UserAgentOptions';
import IKeyStore from '../../keyStore/IKeyStore';
import { IJwsSigningOptions } from '../jose/IJoseOptions';
import { PublicKey } from '../../..';
import { TSMap } from 'typescript-map';
import JoseConstants from '../jose/JoseConstants';
import CryptoProtocolError from '../CryptoProtocolError';
/**
* Named Arguments of Did Protocol
*/
export interface DidProtocolOptions {
/**
* Identifier who wants to send requests.
*/
sender: Identifier;
/**
* Resolver for resolving identifier documents
*/
resolver: IResolver;
}
/**
* Hub Protocol for decrypting/verifying and encrypting/signing payloads
*/
export default class DidProtocol {
/**
* Client's Identifier to be used for signing and decrypting.
*/
private sender: Identifier;
/**
* Resolver for resolving Identifier Documents
*/
private resolver: IResolver;
/**
* Crypto factory defining the crypto API
*/
private cryptoFactory: CryptoFactory;
/**
* Key store for storing keys
*/
private keyStore: IKeyStore;
/**
* User agent options
*/
private options: UserAgentOptions;
/**
* Authentication constructor
* @param options Arguments to a constructor in a named object
*/
constructor (options: DidProtocolOptions) {
this.sender = options.sender;
this.resolver = options.resolver;
this.options = <UserAgentOptions>this.sender.options;
this.cryptoFactory = this.options.cryptoFactory;
this.keyStore = this.options.keyStore;
}
/**
* Unwrapping method for unwrapping requests/responses.
* Decrypt a cipher using [PrivateKey] of Client Identifier and then verify payload.
* @param encryptionKeyReference key reference of private key in keystore used to decrypt.
* @param cipher the cipher to be decrypted and verified by client Identifier.
*/
public async decryptAndVerify(encryptionKeyReference: string, cipher: Buffer): Promise<any> {
// decrypt payload.
const jws = await this.sender.decrypt(cipher, encryptionKeyReference);
// get identifier id from key id in header.
const options = <IJwsSigningOptions> {
cryptoFactory: this.cryptoFactory};
const token : JwsToken = await JwsToken.deserialize(jws, options);
let kid = undefined;
if (token.signatures[0].protected && token.signatures[0].protected.get(JoseConstants.Kid)) {
kid = token.signatures[0].protected.get(JoseConstants.Kid);
} else if (token.signatures[0].header && token.signatures[0].header.get(JoseConstants.Kid)) {
kid = token.signatures[0].header.get(JoseConstants.Kid);
}
if (!kid) {
throw new CryptoProtocolError('DidProtocol', 'The jws token does not contain a kid in protected or header');
}
const id = kid.split('#')[0];
const identifier = new Identifier(id, this.options);
let payload = await identifier.verify(jws);
return JSON.parse(payload);
}
/**
* Wrapping method for wrapping requests/responses.
* Sign a payload using [PrivateKey] in client's keystore and encrypt payload using [PublicKey]
* @param payload the payload to be signed and encrypted by client Identifier.
* #param receiverId identifier for the receiver.
*/
public async signAndEncrypt(payload: any, receiverId: string): Promise<string> {
let stringifiedPayload: string;
if (typeof(payload) === 'string') {
stringifiedPayload = payload;
} else {
stringifiedPayload = JSON.stringify(payload);
}
const jws = await this.sender.sign(stringifiedPayload, <string>(<UserAgentOptions>this.sender.options).cryptoOptions.signingKeyReference);
// create User Agent Options for Identifier
const receiverIdentifier = new Identifier(receiverId, this.options);
return receiverIdentifier.encrypt(jws);
}
}