UNPKG

@0xpolygonid/js-sdk

Version:
130 lines (105 loc) 3.79 kB
import { Resolvable } from 'did-resolver'; import { byteDecoder, byteEncoder } from '../../utils'; import { AcceptJweKEKAlgorithms, MediaType, ProtocolVersion, VerificationMethodType } from '../constants'; import { BasicMessage, DIDDocument, IPacker, PackerParams } from '../types'; import { getRecipientsJWKs, parseAcceptProfile } from '../utils'; import { DID } from '@iden3/js-iden3-core'; import { JoseService } from '../services'; import { FlattenedJWE, GeneralJWE } from 'jose'; export type RecipientInfo = { did: DID; didDocument?: DIDDocument; keyType?: VerificationMethodType; alg?: AcceptJweKEKAlgorithms; }; export type JWEPackerParams = PackerParams & { enc: string; recipients: RecipientInfo[]; }; export class AnonCryptPacker implements IPacker { private readonly _supportedProtocolVersions = [ProtocolVersion.V1]; private _supportedAlgorithms = [ AcceptJweKEKAlgorithms.RSA_OAEP_256, AcceptJweKEKAlgorithms.ECDH_ES_A256KW ]; constructor( private readonly _joseService: JoseService, private readonly _documentResolver: Resolvable ) {} packMessage(msg: BasicMessage, param: JWEPackerParams): Promise<Uint8Array> { return this.packInternal(msg, param); } getSupportedAlgorithms(): AcceptJweKEKAlgorithms[] { return this._supportedAlgorithms; } registerSupportedAlgorithm(algorithm: AcceptJweKEKAlgorithms): void { this._supportedAlgorithms = [...new Set([...this._supportedAlgorithms, algorithm])]; } /** * creates JSON Web Signature token * * @param {Uint8Array} payload - serialized message * @param {PackerParams} params - sender id and proving alg are required * @returns `Promise<Uint8Array>` */ async pack(payload: Uint8Array, params: JWEPackerParams): Promise<Uint8Array> { const message = JSON.parse(byteDecoder.decode(payload)); return this.packInternal(message, params); } async unpack(envelope: Uint8Array): Promise<BasicMessage> { const { plaintext } = await this._joseService.decrypt( JSON.parse(byteDecoder.decode(envelope)) as GeneralJWE | FlattenedJWE ); return JSON.parse(byteDecoder.decode(plaintext)) as BasicMessage; } mediaType(): MediaType { return MediaType.EncryptedMessage; } /** {@inheritDoc IPacker.getSupportedProfiles} */ getSupportedProfiles(): string[] { return this._supportedProtocolVersions.map( (v) => `${v};env=${this.mediaType()};alg=${this._supportedAlgorithms.join(',')}` ); } /** {@inheritDoc IPacker.isProfileSupported} */ isProfileSupported(profile: string): boolean { const { protocolVersion, env, circuits, alg } = parseAcceptProfile(profile); if (!this._supportedProtocolVersions.includes(protocolVersion)) { return false; } if (env !== this.mediaType()) { return false; } if (circuits) { throw new Error(`Circuits are not supported for ${env} media type`); } return Boolean( alg?.some((a) => this._supportedAlgorithms.includes(a as AcceptJweKEKAlgorithms)) ); } private async packInternal(message: BasicMessage, params: JWEPackerParams): Promise<Uint8Array> { const { enc, recipients } = params; if (!enc) { throw new Error('Missing encryption algorithm'); } if (!recipients.length) { throw new Error('Missing recipients'); } if (!message.to) { throw new Error('Missing recipient DID'); } const recipientsJwks = await getRecipientsJWKs(recipients, this._documentResolver); const msg = byteEncoder.encode(JSON.stringify(message)); const jwe = await this._joseService.encrypt(msg, { enc, typ: MediaType.EncryptedMessage, recipients: recipientsJwks }); return byteEncoder.encode(JSON.stringify(jwe)); } }